Important packages:

setwd("Dataset")
Warning: The working directory was changed to C:/Users/DELL/Documents/GitHub/Project_IT326/Dataset inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
Dataset <- read.csv("data.csv")
Preprocessed_dataset <-  read.csv("preprocessed_dataset.csv") 
if(!require(ggplot2)){
install.packages("ggplot2")}
library(ggplot2)
if(!require(dplyr)){
install.packages("dplyr")}
library(dplyr) 
if(!require(dplyr)){
install.packages("dplyr")}
library(dplyr)
if(!require(ltm)){
install.packages("ltm")}
library(ltm)
if (!require(cluster, quietly = TRUE)) {
  install.packages("cluster")
}
if (!require(factoextra, quietly = TRUE)) {
  install.packages("factoextra")
}
 
if (!require(caret, quietly = TRUE)) {
  install.packages("caret")
}

if (!require(partykit, quietly = TRUE)) {
  install.packages("partykit")
}

if (!require(rpart, quietly = TRUE)) {
  install.packages("rpart")
}
if (!require(rpart.plot, quietly = TRUE)) {
  install.packages("rpart.plot")
}
if (!require(tidyverse, quietly = TRUE)) {
  install.packages("tidyverse")
}
 

IT326 Project

_________________________________________________________________________________________________________

The Goal

Our primary objective of this analysis is to classify whatever a student will go to college or not using the classification methods and to identify the main factors and reasons why students are less likely to pursue higher education indicated by “will_go_to_college” being ‘False’. By leveraging the provided dataset with attributes such as school type, school accreditation, gender, interest in college, residence, we aim to discover the most influential variables and their relationships with the decision not to attend college.

The Source

Kaggle.com

General information

  • Number of attributes : 11
  • Number of rows (objects) : 1000
  • The class label: The class label in our project is the attribute “will_go_to_college”. This attribute is binary, meaning that it can take on two values: True for yes or False for no. The value of this attribute will be the target variable that we are trying to predict during our project.

Attribute Description Type Possible values
type_school The type of school the student attends Binary Academic / Vocational
school_accreditation The quality if school Binary A / B (A is better than B)
gender The student’s gender Binary Male / Female
interest The student’s interest in going to college Nominal Very interested /Interested / Less Interested / Not Interested /Uncertain
residence The student’s residence Binary Urban / Rural
parent_age The age of the student’s parents Numeric 40 - 65
parent_salary

The monthly salary of the student’s parents in IDR/Rupiah.

[1Rupiah = 0.00024SAR]

Numeric 1000K - 10M
house_area The size of the student’s house in meter square Numeric 20 - 120
average_grades The student’s average grades in school. Numeric 75 - 98
parent_was_in_college Whether the student’s parents attended college. Binary True - False
will_go_to_college Whether the student plans to go to college. Binary True - False

Sample of our data

head(Dataset)

Here are a sample of 6 row from our dataset.

Missing values

sum(is.na(Dataset))
[1] 0

There are no missing values in our dataset.

Statistical graphs

Graph 1:

df =data.frame(Dataset)
ggplot(data=df, aes(x = interest, fill = will_go_to_college)) +
  geom_bar() +
  scale_x_discrete(limits = c('Not Interested', 'Less Interested', 'Uncertain', 'Interested', 'Very Interested')) +
  labs(title = 'College interest vs College attendance ') +
  scale_fill_manual(values = c("True" = "antiquewhite2", "False" = "antiquewhite3")) +
  theme_minimal()

NA
NA

According to the graph, whether students are interested in going to college or not does not affect whether they actually end up attending Collage . There is a group of individuals who were interested in attending but did not receive acceptance, while others who were not interested were accepted.

Graph 2:


filtered_True =filter(Dataset, will_go_to_college == 'True')
filtered_False =subset(Dataset, will_go_to_college =='False')

ggplot() +
  geom_density(data = filtered_True, aes(x = average_grades, fill = "Going to College"), alpha = 0.5) +
  geom_density(data = filtered_False, aes(x = average_grades, fill = "NOT Going to College"), alpha = 0.5) +
  labs(x = "Average Grades", y = "Density") +
  ggtitle("Comparison of Average Grades for Students Going to College and NOT Going to College") +
  scale_fill_manual(values = c("Going to College" = "antiquewhite4", "NOT Going to College" = "antiquewhite1"))

The graph shows that the average grades for students who had accepted to go to college were higher than those who did not enter college , and this indicates the existence of a correlation between those who going to college and the average grades

Graph 3:

Dataset_percentage <- Dataset %>%
  group_by(type_school) %>%
  summarise(percentage = mean(will_go_to_college == "True") * 100)

# Create a percentage chart
ggplot(Dataset_percentage, aes(x = type_school, y = percentage, fill = type_school)) +
  geom_bar(stat = "identity") +
  labs(title = "Percentage of Students Going to College by Type of School",
       x = "Type of School",
       y = "Percentage") +
  scale_fill_manual(values = c("Academic" = "antiquewhite3", "Vocational" = "antiquewhite2")) +
  theme_minimal()

NA
NA

This graph shows the impact of the type of high school attended by students on their college attendance . Based on the bar chart:

  • among students from Academic high schools, 313 are going to college, and 296 are not.

  • among students from Vocational high schools, 187 are going to college, and 204 are not

These information tell us that a higher proportion of students from academic high schools are going to college compared to those from vocational schools which suggest that the type of school attended.

Graph 4:

ggplot(Dataset, aes(x = average_grades)) +
  geom_histogram(binwidth = 5, fill = "antiquewhite2", color = "antiquewhite4") +
  labs(title = "Distribution of students' grades",
       x = "Students' average grades",
       y = "Frequency") +
  theme_minimal()

This histogram show us that the majority of the students in the dataset are performing well since it seems like their grades are spanning between 75 and 98. This analysis will help us determine whether the academic performance level of students is a contributing factor to their college attendance or not.

Statistical Measures

  1. The student’s academic performance analysis:
summary(Dataset$average_grades)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  75.00   83.74   85.58   86.10   88.26   98.00 

The student grades in our dataset range from 75.00 to 98.00, with a median of 85.58 and an average of 86.10. This suggests that most students are doing well as none of them have average grades below 50. However, it’s interesting to note that some students have much higher or lower grades than the average, mainly due to the wide range of grades..

  1. The socioeconomic status of students’ families analysis:
summary(Dataset$parent_salary)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
 1000000  4360000  5440000  5381570  6382500 10000000 

In the dataset, we’ve got students parents with salaries ranging from 1,000,000 to 10,000,000 IDR/Rupiah. The median salary is 5,440,000 IDR/Rupiah, and the average is 5,381,570 IDR/Rupiah. This data tells us that many parents in our dataset earn less than the average salary in Indonesia, which is 146,000,000 IDR. This suggests that quite a few students in our dataset come from families with limited finances. And this financial situation could certainly impact their ability to get through college.

summary(Dataset$house_area)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  20.00   64.60   75.50   74.52   84.83  120.00 

Additionally we can utilize the house area attribute to gain a deeper understanding of the socioeconomic status of students’ families, where students with houses significantly larger than the mean might indicate a higher socioeconomic status, while those with houses considerably smaller than the mean might reflect a comparatively lower socioeconomic status. Based on the shown output, the house areas range from [20.00-120.00 ㎡]. The median house area is 75.50 ㎡ indicates that families with house areas around this value likely have moderate socioeconomic status with houses that neither very small nor very large.

  1. Understanding Parent Age Range and Variation in its Values
summary(Dataset$parent_age)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  40.00   50.00   52.00   52.21   54.00   65.00 
SD=sd(Dataset$parent_age)
MeanAge=mean(Dataset$parent_age)
cat("coefficient of variation:",SD/MeanAge*100,"%")
coefficient of variation: 6.704771 %

This summary provides the range for age attribute [40,65] which indicates that all parent in middle age during this age parent have more concern about their children , the coefficient of variation= 6.7% which indicates lower variation ,and the value of attribute parent_agerare are relatively close to the mean overall 25% of them have an age below or equal to 50 , 75% have an age below or equal to 54 and the median value is 52

Outliers analysis

###parent age outliers
quartiles <- quantile(Dataset$parent_age, probs=c(.25, .75), na.rm = FALSE)
IQR <- IQR(Dataset$parent_age)

Lower <- quartiles[1] - 1.5*IQR
Upper <- quartiles[2] + 1.5*IQR 

data_no_outlier <- subset(Dataset, Dataset$parent_age > Lower & Dataset$parent_age < Upper)
dim(data_no_outlier)
[1] 957  11
###parent salary outliers
quartiles <- quantile(Dataset$parent_salary, probs=c(.25, .75), na.rm = FALSE)
IQR <- IQR(Dataset$parent_salary)

Lower <- quartiles[1] - 1.5*IQR
Upper <- quartiles[2] + 1.5*IQR 

data_no_outlier <- subset(data_no_outlier, data_no_outlier$parent_salary> Lower & data_no_outlier$parent_salary < Upper)
dim(data_no_outlier)
[1] 955  11
###averge grades outliers
quartiles <- quantile(Dataset$average_grades, probs=c(.25, .75), na.rm = FALSE)
IQR <- IQR(Dataset$average_grades)

Lower <- quartiles[1] - 1.5*IQR
Upper <- quartiles[2] + 1.5*IQR 

data_no_outlier <- subset(data_no_outlier, data_no_outlier$average_grades> Lower & data_no_outlier$average_grades < Upper)
dim(data_no_outlier)
[1] 944  11
###house area outliers
quartiles <- quantile(Dataset$house_area, probs=c(.25, .75), na.rm = FALSE)
IQR <- IQR(Dataset$house_area)

Lower <- quartiles[1] - 1.5*IQR
Upper <- quartiles[2] + 1.5*IQR 

data_no_outlier <- subset(data_no_outlier, data_no_outlier$house_area> Lower & data_no_outlier$house_area < Upper)

Founded_Outliers=data.frame(anti_join(Dataset,data_no_outlier))
Joining with `by = join_by(type_school, school_accreditation, gender, interest, residence, parent_age, parent_salary, house_area, average_grades, parent_was_in_college, will_go_to_college)`
print(Founded_Outliers)

After conducting data analysis and identifying outliers, our inspection reveals that the detected outliers represent inherent variation within the population. Regarding Parent_age, outliers are observed for values below 44 and above 65. However, it should be noted the age from 40 to 65 fall within the expected mean of our dataset meaning that it doesn’t indicate that they are outliers . For parent_salary, we found two outliers: one below 1,326,250 ind ≈ 85 USD and another above 9,416,250 ind ≈ 606 USD. The minimum and maximum values were determined to be 1,000,000 ind ≈ 64 USD and 10,000,000 ind ≈ 644 USD, respectively. In the case of grades, twelve outliers were identified, ranging from below 76 to above 97. Nevertheless, since the data falls within the acceptable range of 0 to 100, these outliers should be retained as they are still considered normal and within the usual grade range. Finally, for house_area, we found eleven outliers below 34.4m and above 115m, with the minimum being 20m and the maximum being 120m. However, these values are still considered typical for the population.

Normalization

normalize <- function(x) {return((x-min(x))/ (max(x)-min(x)))}
datasetWithoutNormalization<-Dataset
Dataset$parent_salary<-normalize(datasetWithoutNormalization$parent_salary)
Dataset$house_area<-normalize(datasetWithoutNormalization$house_area)
print(Dataset)

We applied normalization to the ‘parent_salary’ and ‘house_area’ attributes, scaling their values to a range between 0 and 1. This normalization process greatly facilitates data handling and analysis, ensuring that these attributes are on a consistent scale. Which will improve the reliability of our data analysis and enable better conclusions to be drawn from the dataset. Normalization is a crucial step in preparing the data for modeling, as it prevents attributes with larger numerical ranges from dominating the analysis and ensures fair treatment for all features.

Discretization



Dataset$average_grades [Dataset$average_grades >= 95] <- '+A'
Dataset$average_grades [95 >Dataset$average_grades & Dataset$average_grades >= 90] <- 'A'
Dataset$average_grades [90 >Dataset$average_grades & Dataset$average_grades >= 85] <- '+B'
Dataset$average_grades [85 >Dataset$average_grades & Dataset$average_grades >= 80] <- 'B'
Dataset$average_grades [80 >Dataset$average_grades & Dataset$average_grades >= 75] <- '+C'
Dataset$average_grades [75 >Dataset$average_grades & Dataset$average_grades >= 70] <- 'C'
Dataset$average_grades [70 >Dataset$average_grades & Dataset$average_grades >= 65] <- '+D'
Dataset$average_grades [65 >Dataset$average_grades & Dataset$average_grades >= 60] <- 'D'
Dataset$average_grades [60 >Dataset$average_grades & Dataset$average_grades >= 0] <- 'F'
Dataset$average_grades <- as.character(Dataset$average_grades )
print(Dataset)

We transformed the parent_age attribute into intervals by dividing the values to be fall on one of two possible interval labels with equal width which is(40,50],(50,60] by discretization the values well be simpler to classify or perform other methods that can help us later in our model.

and to better utilize and interpret the grades attributes for each student, we have converted the numeric grades into letter grades (A+, A, B+, B, C+, C, D+, D, F). This transformation was undertaken to focus on the general letter grade representation rather than the precise numerical values.

Encoding

Dataset$parent_was_in_college[Dataset$parent_was_in_college=="TRUE"]<-1
Dataset$parent_was_in_college[Dataset$parent_was_in_college=="True"]<-1
Dataset$parent_was_in_college[Dataset$parent_was_in_college=="FALSE"]<-0
Dataset$parent_was_in_college[Dataset$parent_was_in_college=="False"]<-0

Dataset$will_go_to_college[Dataset$will_go_to_college=="TRUE"]<-0
Dataset$will_go_to_college[Dataset$will_go_to_college=="True"]<-0
Dataset$will_go_to_college[Dataset$will_go_to_college=="FALSE"]<-1
Dataset$will_go_to_college[Dataset$will_go_to_college=="False"]<-1

Dataset$gender[Dataset$gender=="Female"]<-1
Dataset$gender[Dataset$gender=="Male"]<-0

Dataset$school_accreditation[Dataset$school_accreditation=="A"]<-1
Dataset$school_accreditation[Dataset$school_accreditation=="B"]<-0

Dataset$interest[Dataset$interest=="Very Interested"]<-4
Dataset$interest[Dataset$interest=="Interested"]<-3
Dataset$interest[Dataset$interest=="Less Interested"]<-2
Dataset$interest[Dataset$interest=="Not Interested"]<-1
Dataset$interest[Dataset$interest=="Uncertain"]<-0


Dataset$type_school[Dataset$type_school=="Academic"]<-1 
Dataset$type_school[Dataset$type_school=="Vocational"]<-0

Dataset$residence[Dataset$residence=="Urban"]<-1
Dataset$residence[Dataset$residence=="Rural"]<-0
print(Dataset)

Since encoding is an important step in data preprocessing that enables the use of categorical data in various data analysis and machine learning tasks, we encoded attributes like the ‘parent was in college’ attribute from (True, False) to (1, 0), and ‘will go to college’ from (True, False) to (0, 1). This encoding is carried out as we aim to predict the influencing factors. Additionally, we encoded the ‘gender’ attribute from (Female, Male) to (1, 0), ‘school accreditation’ from (A, B) to (1, 0), ‘type_school’ from (Academic, Vocational) to (1, 0), ‘residence’ from (Urban, Rural) to (1, 0), and ‘interest’ from (Very interested ,Interested , Less Interested , Not Interested ,Uncertain ) to (4,3,2, 1, 0) respectively. Encoding serves to simplify the data, reduce complexity, and enhance its suitability for modeling purposes.

Correlation analysis Chi square test for nominal attribute:


#1
C=chisq.test(Dataset$type_school , Dataset$will_go_to_college)
print(C)

    Pearson's Chi-squared test with Yates' continuity correction

data:  Dataset$type_school and Dataset$will_go_to_college
X-squared = 1.0751, df = 1, p-value = 0.2998
#2

C=chisq.test(Dataset$school_accreditation , Dataset$will_go_to_college)
print(C)

    Pearson's Chi-squared test with Yates' continuity correction

data:  Dataset$school_accreditation and Dataset$will_go_to_college
X-squared = 0.78513, df = 1, p-value = 0.3756
#3
C=chisq.test(Dataset$gender , Dataset$will_go_to_college)
print(C)

    Pearson's Chi-squared test with Yates' continuity correction

data:  Dataset$gender and Dataset$will_go_to_college
X-squared = 1.0249, df = 1, p-value = 0.3114
#4
C=chisq.test(Dataset$interest , Dataset$will_go_to_college)
print(C)

    Pearson's Chi-squared test

data:  Dataset$interest and Dataset$will_go_to_college
X-squared = 73.337, df = 4, p-value = 4.477e-15
#5
C=chisq.test(Dataset$residence , Dataset$will_go_to_college)
print(C)

    Pearson's Chi-squared test with Yates' continuity correction

data:  Dataset$residence and Dataset$will_go_to_college
X-squared = 0.016098, df = 1, p-value = 0.899
#6
C=chisq.test(Dataset$average_grades , Dataset$will_go_to_college)
print(C)

    Pearson's Chi-squared test

data:  Dataset$average_grades and Dataset$will_go_to_college
X-squared = 261.89, df = 4, p-value < 2.2e-16
#7
C=chisq.test(Dataset$parent_was_in_college , Dataset$will_go_to_college)
print(C)

    Pearson's Chi-squared test with Yates' continuity correction

data:  Dataset$parent_was_in_college and Dataset$will_go_to_college
X-squared = 2.1194, df = 1, p-value = 0.1454

All the attributes have X-square greater than the p-value which indicate a some association with the class label; therefore we reject the null hypothesis

we noticed for ‘interest’ and ‘average grade’ the analysis shows that X-square is much larger than p-value indicate the significant association of the two attributes with the decision of the student to go to the collage or not

Correlation coefficient analysis for numeric attribute:


biserial.cor(Dataset$parent_salary,Dataset$will_go_to_college, c("all.obs", "complete.obs"), level = 1)
[1] 0.4756928
biserial.cor(Dataset$house_area,Dataset$will_go_to_college, c("all.obs", "complete.obs"), level = 1)
[1] 0.4672669
biserial.cor(Dataset$parent_age,Dataset$will_go_to_college,c("all.obs", "complete.obs"), level = 1)
[1] 0.04287336
 
 

the analysis shows moderate correlation coefficient for parent salary and house area with the class label which indicate that they are relevant factors meaning that the higher the parent salary and the larger house area the higher probability for a student to enroll in a collage

where is the on other hand, the correlation coefficient for the parent age is very small which indicate that the parent age has little impact to the probability for student to enroll in a collage

Feature selection:

ultimately based on the analysis of the correlation that we conducted on the relationship of the dataset attributes with the class label, and the understanding of the data and the context of each attribute and potential relevance to the class label we decided to not delete any of the attribute

Classification:

factor the data


data <- Preprocessed_dataset


data$will_go_to_college <- as.factor(data$will_go_to_college)
data$residence <- as.factor(data$residence)
data$gender <- as.factor(data$gender)
data$parent_was_in_college <- as.factor(data$parent_was_in_college)
data$interest <- as.factor(data$interest)
data$type_school <- as.factor(data$type_school)
data$school_accreditation <- as.factor(data$school_accreditation)

data$average_grades <- as.factor(data$average_grades)
str(data)
'data.frame':   1000 obs. of  11 variables:
 $ type_school          : Factor w/ 2 levels "0","1": 2 2 2 1 2 1 2 2 2 2 ...
 $ school_accreditation : Factor w/ 2 levels "0","1": 2 2 1 1 2 1 2 1 1 1 ...
 $ gender               : Factor w/ 2 levels "0","1": 1 1 2 1 2 2 1 1 2 2 ...
 $ interest             : Factor w/ 5 levels "0","1","2","3",..: 3 3 5 5 5 3 5 5 1 5 ...
 $ residence            : Factor w/ 2 levels "0","1": 2 2 2 1 2 1 1 1 1 1 ...
 $ parent_age           : int  56 57 50 49 57 48 52 53 52 47 ...
 $ parent_salary        : num  0.661 0.379 0.611 0.622 0.472 ...
 $ house_area           : num  0.63 0.568 0.606 0.582 0.551 0.453 0.655 0.633 0.603 0.48 ...
 $ average_grades       : Factor w/ 5 levels "+A","+B","+C",..: 5 2 2 5 2 2 4 5 2 2 ...
 $ parent_was_in_college: Factor w/ 2 levels "0","1": 1 1 1 2 1 2 2 2 2 2 ...
 $ will_go_to_college   : Factor w/ 2 levels "0","1": 1 1 1 1 2 2 1 2 1 2 ...

balanced or imbalanced


library(tidyverse) 
library(caret)
data$will_go_to_college<- as.numeric(data$will_go_to_college)
hist(data$will_go_to_college,col="coral")

prop.table(table(data$will_go_to_college))

  1   2 
0.5 0.5 

we want to confirm that the distribution between the two label data is not too much different. Because imbalanced datasets can lead to imbalanced accuracy.

Fortunately ,our data is balanced

partition method

We opted for cross-validation as our partition method owing to the constraints posed by limited data availability. To ensure robustness in our evaluation, we employed three distinct values for k folds 2, 3, and 4. we chose small k folds because of our small data

c4.5

library(caret)
library(rpart)
library(dplyr)
library(rpart.plot)

set.seed(123)
fold <- c(2, 3, 4)  # Values of xval (number of folds) to try

for (fold in fold) {
  cat("fold =", fold, "\n")
  trctrl <- trainControl(method = "cv", number = fold, savePredictions = TRUE)
  c45_fit <- train(factor(will_go_to_college) ~ ., data = data, method = "J48", trControl = trctrl)
   print(c45_fit$finalModel)
  # Get predicted values
  predictions <- predict(c45_fit, newdata = data)
  
  # Create confusion matrix
  confusion_matrix <- confusionMatrix(predictions, data$will_go_to_college)
  
  # Print the confusion matrix
  print(confusion_matrix)
  
  # Print accuracy for each fold
  pred <- c45_fit$pred
  pred$equal <- ifelse(pred$pred == pred$obs, 1, 0)
  eachfold <- pred %>%
    group_by(Resample) %>%
    summarise_at(vars(equal),
                 list(Accuracy = mean))
  print(eachfold)
    # Plot decision tree
plot(c45_fit$finalModel, main = fold)
  
}
fold = 2 
J48 pruned tree
------------------

average_gradesA <= 0
|   parent_salary <= 0.416667
|   |   house_area <= 0.559: 1 (207.0/6.0)
|   |   house_area > 0.559
|   |   |   parent_was_in_college1 <= 0
|   |   |   |   parent_salary <= 0.368889
|   |   |   |   |   average_grades+C <= 0
|   |   |   |   |   |   parent_age <= 60: 1 (19.0/2.0)
|   |   |   |   |   |   parent_age > 60: 0 (2.0)
|   |   |   |   |   average_grades+C > 0: 0 (5.0)
|   |   |   |   parent_salary > 0.368889: 0 (20.0/1.0)
|   |   |   parent_was_in_college1 > 0
|   |   |   |   type_school1 <= 0: 1 (28.0)
|   |   |   |   type_school1 > 0
|   |   |   |   |   average_grades+B <= 0
|   |   |   |   |   |   average_gradesB <= 0
|   |   |   |   |   |   |   interest2 <= 0: 0 (5.0)
|   |   |   |   |   |   |   interest2 > 0: 1 (1.0)
|   |   |   |   |   |   average_gradesB > 0: 1 (9.0)
|   |   |   |   |   average_grades+B > 0: 1 (12.0)
|   parent_salary > 0.416667
|   |   house_area <= 0.413
|   |   |   interest3 <= 0
|   |   |   |   type_school1 <= 0
|   |   |   |   |   gender1 <= 0
|   |   |   |   |   |   school_accreditation1 <= 0: 1 (3.0)
|   |   |   |   |   |   school_accreditation1 > 0
|   |   |   |   |   |   |   parent_was_in_college1 <= 0
|   |   |   |   |   |   |   |   parent_age <= 53: 1 (9.0)
|   |   |   |   |   |   |   |   parent_age > 53: 0 (2.0)
|   |   |   |   |   |   |   parent_was_in_college1 > 0
|   |   |   |   |   |   |   |   parent_age <= 51: 0 (3.0)
|   |   |   |   |   |   |   |   parent_age > 51: 1 (1.0)
|   |   |   |   |   gender1 > 0
|   |   |   |   |   |   average_grades+B <= 0
|   |   |   |   |   |   |   house_area <= 0.348: 0 (3.0)
|   |   |   |   |   |   |   house_area > 0.348: 1 (2.0)
|   |   |   |   |   |   average_grades+B > 0: 0 (6.0)
|   |   |   |   type_school1 > 0
|   |   |   |   |   school_accreditation1 <= 0
|   |   |   |   |   |   parent_salary <= 0.524444: 1 (6.0)
|   |   |   |   |   |   parent_salary > 0.524444: 0 (2.0)
|   |   |   |   |   school_accreditation1 > 0: 1 (26.0)
|   |   |   interest3 > 0: 1 (28.0)
|   |   house_area > 0.413
|   |   |   average_gradesB <= 0
|   |   |   |   type_school1 <= 0
|   |   |   |   |   interest2 <= 0
|   |   |   |   |   |   interest3 <= 0
|   |   |   |   |   |   |   interest4 <= 0
|   |   |   |   |   |   |   |   residence1 <= 0
|   |   |   |   |   |   |   |   |   school_accreditation1 <= 0
|   |   |   |   |   |   |   |   |   |   parent_salary <= 0.676667: 1 (36.0/5.0)
|   |   |   |   |   |   |   |   |   |   parent_salary > 0.676667
|   |   |   |   |   |   |   |   |   |   |   house_area <= 0.5: 1 (1.0)
|   |   |   |   |   |   |   |   |   |   |   house_area > 0.5: 0 (3.0)
|   |   |   |   |   |   |   |   |   school_accreditation1 > 0
|   |   |   |   |   |   |   |   |   |   house_area <= 0.634
|   |   |   |   |   |   |   |   |   |   |   parent_salary <= 0.538889: 1 (11.0)
|   |   |   |   |   |   |   |   |   |   |   parent_salary > 0.538889
|   |   |   |   |   |   |   |   |   |   |   |   parent_was_in_college1 <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   interest1 <= 0: 1 (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   interest1 > 0: 0 (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   parent_was_in_college1 > 0: 0 (4.0)
|   |   |   |   |   |   |   |   |   |   house_area > 0.634: 0 (6.0)
|   |   |   |   |   |   |   |   residence1 > 0
|   |   |   |   |   |   |   |   |   house_area <= 0.462: 0 (4.0)
|   |   |   |   |   |   |   |   |   house_area > 0.462
|   |   |   |   |   |   |   |   |   |   parent_age <= 52: 0 (2.0)
|   |   |   |   |   |   |   |   |   |   parent_age > 52: 1 (4.0/1.0)
|   |   |   |   |   |   |   interest4 > 0
|   |   |   |   |   |   |   |   residence1 <= 0
|   |   |   |   |   |   |   |   |   parent_age <= 48: 1 (2.0)
|   |   |   |   |   |   |   |   |   parent_age > 48
|   |   |   |   |   |   |   |   |   |   school_accreditation1 <= 0
|   |   |   |   |   |   |   |   |   |   |   parent_salary <= 0.587778: 1 (3.0)
|   |   |   |   |   |   |   |   |   |   |   parent_salary > 0.587778: 0 (6.0/1.0)
|   |   |   |   |   |   |   |   |   |   school_accreditation1 > 0: 0 (18.0/1.0)
|   |   |   |   |   |   |   |   residence1 > 0: 0 (13.0)
|   |   |   |   |   |   interest3 > 0: 0 (7.0)
|   |   |   |   |   interest2 > 0: 0 (24.0)
|   |   |   |   type_school1 > 0
|   |   |   |   |   school_accreditation1 <= 0: 0 (95.0/2.0)
|   |   |   |   |   school_accreditation1 > 0
|   |   |   |   |   |   residence1 <= 0
|   |   |   |   |   |   |   interest2 <= 0
|   |   |   |   |   |   |   |   interest4 <= 0: 0 (10.0)
|   |   |   |   |   |   |   |   interest4 > 0
|   |   |   |   |   |   |   |   |   parent_salary <= 0.606667: 1 (3.0)
|   |   |   |   |   |   |   |   |   parent_salary > 0.606667: 0 (2.0)
|   |   |   |   |   |   |   interest2 > 0: 1 (2.0)
|   |   |   |   |   |   residence1 > 0
|   |   |   |   |   |   |   parent_salary <= 0.503333
|   |   |   |   |   |   |   |   interest2 <= 0
|   |   |   |   |   |   |   |   |   house_area <= 0.665
|   |   |   |   |   |   |   |   |   |   parent_age <= 53
|   |   |   |   |   |   |   |   |   |   |   parent_salary <= 0.496667: 0 (4.0)
|   |   |   |   |   |   |   |   |   |   |   parent_salary > 0.496667: 1 (1.0)
|   |   |   |   |   |   |   |   |   |   parent_age > 53: 1 (5.0)
|   |   |   |   |   |   |   |   |   house_area > 0.665: 0 (4.0)
|   |   |   |   |   |   |   |   interest2 > 0: 0 (5.0)
|   |   |   |   |   |   |   parent_salary > 0.503333: 0 (41.0/1.0)
|   |   |   average_gradesB > 0
|   |   |   |   residence1 <= 0
|   |   |   |   |   house_area <= 0.635: 1 (59.0/6.0)
|   |   |   |   |   house_area > 0.635
|   |   |   |   |   |   parent_age <= 46: 1 (4.0)
|   |   |   |   |   |   parent_age > 46
|   |   |   |   |   |   |   interest2 <= 0: 0 (17.0/2.0)
|   |   |   |   |   |   |   interest2 > 0
|   |   |   |   |   |   |   |   type_school1 <= 0: 0 (1.0)
|   |   |   |   |   |   |   |   type_school1 > 0: 1 (2.0)
|   |   |   |   residence1 > 0
|   |   |   |   |   parent_was_in_college1 <= 0
|   |   |   |   |   |   school_accreditation1 <= 0
|   |   |   |   |   |   |   parent_salary <= 0.451111: 0 (4.0)
|   |   |   |   |   |   |   parent_salary > 0.451111
|   |   |   |   |   |   |   |   house_area <= 0.503: 0 (2.0)
|   |   |   |   |   |   |   |   house_area > 0.503: 1 (9.0)
|   |   |   |   |   |   school_accreditation1 > 0
|   |   |   |   |   |   |   interest3 <= 0: 0 (45.0/10.0)
|   |   |   |   |   |   |   interest3 > 0
|   |   |   |   |   |   |   |   house_area <= 0.675: 1 (5.0)
|   |   |   |   |   |   |   |   house_area > 0.675: 0 (2.0)
|   |   |   |   |   parent_was_in_college1 > 0: 0 (9.0)
average_gradesA > 0: 0 (123.0/2.0)

Number of Leaves  :     64

Size of the tree :  127

Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 480  20
         1  20 480
                                          
               Accuracy : 0.96            
                 95% CI : (0.9459, 0.9713)
    No Information Rate : 0.5             
    P-Value [Acc > NIR] : <2e-16          
                                          
                  Kappa : 0.92            
                                          
 Mcnemar's Test P-Value : 1               
                                          
            Sensitivity : 0.96            
            Specificity : 0.96            
         Pos Pred Value : 0.96            
         Neg Pred Value : 0.96            
             Prevalence : 0.50            
         Detection Rate : 0.48            
   Detection Prevalence : 0.50            
      Balanced Accuracy : 0.96            
                                          
       'Positive' Class : 0               
                                          
fold = 3 
J48 pruned tree
------------------

average_gradesA <= 0
|   parent_salary <= 0.416667
|   |   house_area <= 0.559: 1 (207.0/6.0)
|   |   house_area > 0.559
|   |   |   parent_was_in_college1 <= 0
|   |   |   |   parent_salary <= 0.368889
|   |   |   |   |   average_grades+C <= 0
|   |   |   |   |   |   parent_age <= 60: 1 (19.0/2.0)
|   |   |   |   |   |   parent_age > 60: 0 (2.0)
|   |   |   |   |   average_grades+C > 0: 0 (5.0)
|   |   |   |   parent_salary > 0.368889: 0 (20.0/1.0)
|   |   |   parent_was_in_college1 > 0
|   |   |   |   type_school1 <= 0: 1 (28.0)
|   |   |   |   type_school1 > 0
|   |   |   |   |   average_grades+B <= 0
|   |   |   |   |   |   average_gradesB <= 0: 0 (6.0/1.0)
|   |   |   |   |   |   average_gradesB > 0: 1 (9.0)
|   |   |   |   |   average_grades+B > 0: 1 (12.0)
|   parent_salary > 0.416667
|   |   house_area <= 0.413
|   |   |   interest3 <= 0
|   |   |   |   type_school1 <= 0
|   |   |   |   |   gender1 <= 0
|   |   |   |   |   |   school_accreditation1 <= 0: 1 (3.0)
|   |   |   |   |   |   school_accreditation1 > 0
|   |   |   |   |   |   |   parent_was_in_college1 <= 0
|   |   |   |   |   |   |   |   parent_age <= 53: 1 (9.0)
|   |   |   |   |   |   |   |   parent_age > 53: 0 (2.0)
|   |   |   |   |   |   |   parent_was_in_college1 > 0: 0 (4.0/1.0)
|   |   |   |   |   gender1 > 0
|   |   |   |   |   |   average_grades+B <= 0
|   |   |   |   |   |   |   house_area <= 0.348: 0 (3.0)
|   |   |   |   |   |   |   house_area > 0.348: 1 (2.0)
|   |   |   |   |   |   average_grades+B > 0: 0 (6.0)
|   |   |   |   type_school1 > 0
|   |   |   |   |   school_accreditation1 <= 0
|   |   |   |   |   |   parent_salary <= 0.524444: 1 (6.0)
|   |   |   |   |   |   parent_salary > 0.524444: 0 (2.0)
|   |   |   |   |   school_accreditation1 > 0: 1 (26.0)
|   |   |   interest3 > 0: 1 (28.0)
|   |   house_area > 0.413
|   |   |   average_gradesB <= 0
|   |   |   |   type_school1 <= 0
|   |   |   |   |   interest2 <= 0
|   |   |   |   |   |   interest4 <= 0
|   |   |   |   |   |   |   residence1 <= 0
|   |   |   |   |   |   |   |   school_accreditation1 <= 0
|   |   |   |   |   |   |   |   |   interest1 <= 0
|   |   |   |   |   |   |   |   |   |   parent_salary <= 0.676667: 1 (24.0/2.0)
|   |   |   |   |   |   |   |   |   |   parent_salary > 0.676667: 0 (6.0/1.0)
|   |   |   |   |   |   |   |   |   interest1 > 0
|   |   |   |   |   |   |   |   |   |   parent_age <= 49
|   |   |   |   |   |   |   |   |   |   |   gender1 <= 0: 1 (2.0)
|   |   |   |   |   |   |   |   |   |   |   gender1 > 0: 0 (3.0)
|   |   |   |   |   |   |   |   |   |   parent_age > 49: 1 (7.0)
|   |   |   |   |   |   |   |   school_accreditation1 > 0
|   |   |   |   |   |   |   |   |   house_area <= 0.634
|   |   |   |   |   |   |   |   |   |   parent_salary <= 0.538889: 1 (11.0)
|   |   |   |   |   |   |   |   |   |   parent_salary > 0.538889
|   |   |   |   |   |   |   |   |   |   |   parent_was_in_college1 <= 0: 1 (3.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   parent_was_in_college1 > 0: 0 (5.0)
|   |   |   |   |   |   |   |   |   house_area > 0.634: 0 (7.0)
|   |   |   |   |   |   |   residence1 > 0
|   |   |   |   |   |   |   |   school_accreditation1 <= 0: 0 (3.0)
|   |   |   |   |   |   |   |   school_accreditation1 > 0
|   |   |   |   |   |   |   |   |   house_area <= 0.467: 0 (4.0)
|   |   |   |   |   |   |   |   |   house_area > 0.467
|   |   |   |   |   |   |   |   |   |   house_area <= 0.556: 1 (3.0)
|   |   |   |   |   |   |   |   |   |   house_area > 0.556: 0 (3.0)
|   |   |   |   |   |   interest4 > 0
|   |   |   |   |   |   |   residence1 <= 0
|   |   |   |   |   |   |   |   parent_age <= 48: 1 (2.0)
|   |   |   |   |   |   |   |   parent_age > 48
|   |   |   |   |   |   |   |   |   school_accreditation1 <= 0
|   |   |   |   |   |   |   |   |   |   parent_salary <= 0.587778: 1 (3.0)
|   |   |   |   |   |   |   |   |   |   parent_salary > 0.587778: 0 (6.0/1.0)
|   |   |   |   |   |   |   |   |   school_accreditation1 > 0: 0 (18.0/1.0)
|   |   |   |   |   |   |   residence1 > 0: 0 (13.0)
|   |   |   |   |   interest2 > 0: 0 (24.0)
|   |   |   |   type_school1 > 0
|   |   |   |   |   school_accreditation1 <= 0: 0 (95.0/2.0)
|   |   |   |   |   school_accreditation1 > 0
|   |   |   |   |   |   residence1 <= 0
|   |   |   |   |   |   |   interest2 <= 0
|   |   |   |   |   |   |   |   interest4 <= 0: 0 (10.0)
|   |   |   |   |   |   |   |   interest4 > 0
|   |   |   |   |   |   |   |   |   parent_salary <= 0.606667: 1 (3.0)
|   |   |   |   |   |   |   |   |   parent_salary > 0.606667: 0 (2.0)
|   |   |   |   |   |   |   interest2 > 0: 1 (2.0)
|   |   |   |   |   |   residence1 > 0
|   |   |   |   |   |   |   parent_salary <= 0.503333
|   |   |   |   |   |   |   |   interest2 <= 0
|   |   |   |   |   |   |   |   |   house_area <= 0.665
|   |   |   |   |   |   |   |   |   |   parent_age <= 53: 0 (5.0/1.0)
|   |   |   |   |   |   |   |   |   |   parent_age > 53: 1 (5.0)
|   |   |   |   |   |   |   |   |   house_area > 0.665: 0 (4.0)
|   |   |   |   |   |   |   |   interest2 > 0: 0 (5.0)
|   |   |   |   |   |   |   parent_salary > 0.503333: 0 (41.0/1.0)
|   |   |   average_gradesB > 0
|   |   |   |   residence1 <= 0
|   |   |   |   |   house_area <= 0.635
|   |   |   |   |   |   parent_was_in_college1 <= 0: 1 (23.0)
|   |   |   |   |   |   parent_was_in_college1 > 0
|   |   |   |   |   |   |   parent_salary <= 0.586667: 1 (22.0/2.0)
|   |   |   |   |   |   |   parent_salary > 0.586667
|   |   |   |   |   |   |   |   parent_age <= 50
|   |   |   |   |   |   |   |   |   type_school1 <= 0
|   |   |   |   |   |   |   |   |   |   house_area <= 0.569: 1 (8.0)
|   |   |   |   |   |   |   |   |   |   house_area > 0.569: 0 (2.0)
|   |   |   |   |   |   |   |   |   type_school1 > 0: 1 (2.0)
|   |   |   |   |   |   |   |   parent_age > 50: 0 (2.0)
|   |   |   |   |   house_area > 0.635
|   |   |   |   |   |   parent_age <= 46: 1 (4.0)
|   |   |   |   |   |   parent_age > 46
|   |   |   |   |   |   |   interest2 <= 0: 0 (17.0/2.0)
|   |   |   |   |   |   |   interest2 > 0: 1 (3.0/1.0)
|   |   |   |   residence1 > 0
|   |   |   |   |   parent_was_in_college1 <= 0
|   |   |   |   |   |   interest1 <= 0
|   |   |   |   |   |   |   school_accreditation1 <= 0
|   |   |   |   |   |   |   |   parent_salary <= 0.451111: 0 (3.0)
|   |   |   |   |   |   |   |   parent_salary > 0.451111: 1 (10.0/1.0)
|   |   |   |   |   |   |   school_accreditation1 > 0
|   |   |   |   |   |   |   |   parent_age <= 57
|   |   |   |   |   |   |   |   |   interest3 <= 0
|   |   |   |   |   |   |   |   |   |   interest2 <= 0
|   |   |   |   |   |   |   |   |   |   |   house_area <= 0.486
|   |   |   |   |   |   |   |   |   |   |   |   type_school1 <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   parent_age <= 54: 1 (4.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   parent_age > 54: 0 (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   type_school1 > 0: 0 (4.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   house_area > 0.486: 0 (14.0)
|   |   |   |   |   |   |   |   |   |   interest2 > 0
|   |   |   |   |   |   |   |   |   |   |   house_area <= 0.497: 1 (2.0)
|   |   |   |   |   |   |   |   |   |   |   house_area > 0.497: 0 (14.0/3.0)
|   |   |   |   |   |   |   |   |   interest3 > 0
|   |   |   |   |   |   |   |   |   |   house_area <= 0.675: 1 (3.0)
|   |   |   |   |   |   |   |   |   |   house_area > 0.675: 0 (2.0)
|   |   |   |   |   |   |   |   parent_age > 57: 1 (3.0)
|   |   |   |   |   |   interest1 > 0: 0 (6.0)
|   |   |   |   |   parent_was_in_college1 > 0: 0 (9.0)
average_gradesA > 0: 0 (123.0/2.0)

Number of Leaves  :     72

Size of the tree :  143

Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 484  18
         1  16 482
                                          
               Accuracy : 0.966           
                 95% CI : (0.9528, 0.9763)
    No Information Rate : 0.5             
    P-Value [Acc > NIR] : <2e-16          
                                          
                  Kappa : 0.932           
                                          
 Mcnemar's Test P-Value : 0.8638          
                                          
            Sensitivity : 0.9680          
            Specificity : 0.9640          
         Pos Pred Value : 0.9641          
         Neg Pred Value : 0.9679          
             Prevalence : 0.5000          
         Detection Rate : 0.4840          
   Detection Prevalence : 0.5020          
      Balanced Accuracy : 0.9660          
                                          
       'Positive' Class : 0               
                                          
fold = 4 
J48 pruned tree
------------------

average_gradesA <= 0
|   parent_salary <= 0.416667
|   |   house_area <= 0.559: 1 (207.0/6.0)
|   |   house_area > 0.559
|   |   |   parent_was_in_college1 <= 0
|   |   |   |   parent_salary <= 0.368889
|   |   |   |   |   average_grades+C <= 0
|   |   |   |   |   |   parent_age <= 60: 1 (19.0/2.0)
|   |   |   |   |   |   parent_age > 60: 0 (2.0)
|   |   |   |   |   average_grades+C > 0: 0 (5.0)
|   |   |   |   parent_salary > 0.368889: 0 (20.0/1.0)
|   |   |   parent_was_in_college1 > 0
|   |   |   |   type_school1 <= 0: 1 (28.0)
|   |   |   |   type_school1 > 0
|   |   |   |   |   average_grades+B <= 0
|   |   |   |   |   |   average_gradesB <= 0
|   |   |   |   |   |   |   interest2 <= 0: 0 (5.0)
|   |   |   |   |   |   |   interest2 > 0: 1 (1.0)
|   |   |   |   |   |   average_gradesB > 0: 1 (9.0)
|   |   |   |   |   average_grades+B > 0: 1 (12.0)
|   parent_salary > 0.416667
|   |   house_area <= 0.413
|   |   |   interest3 <= 0
|   |   |   |   type_school1 <= 0
|   |   |   |   |   gender1 <= 0
|   |   |   |   |   |   school_accreditation1 <= 0: 1 (3.0)
|   |   |   |   |   |   school_accreditation1 > 0
|   |   |   |   |   |   |   parent_was_in_college1 <= 0
|   |   |   |   |   |   |   |   parent_age <= 53: 1 (9.0)
|   |   |   |   |   |   |   |   parent_age > 53: 0 (2.0)
|   |   |   |   |   |   |   parent_was_in_college1 > 0
|   |   |   |   |   |   |   |   parent_age <= 51: 0 (3.0)
|   |   |   |   |   |   |   |   parent_age > 51: 1 (1.0)
|   |   |   |   |   gender1 > 0
|   |   |   |   |   |   average_grades+B <= 0
|   |   |   |   |   |   |   house_area <= 0.348: 0 (3.0)
|   |   |   |   |   |   |   house_area > 0.348: 1 (2.0)
|   |   |   |   |   |   average_grades+B > 0: 0 (6.0)
|   |   |   |   type_school1 > 0
|   |   |   |   |   school_accreditation1 <= 0
|   |   |   |   |   |   parent_salary <= 0.524444: 1 (6.0)
|   |   |   |   |   |   parent_salary > 0.524444: 0 (2.0)
|   |   |   |   |   school_accreditation1 > 0: 1 (26.0)
|   |   |   interest3 > 0: 1 (28.0)
|   |   house_area > 0.413
|   |   |   average_gradesB <= 0
|   |   |   |   type_school1 <= 0
|   |   |   |   |   interest2 <= 0
|   |   |   |   |   |   interest3 <= 0
|   |   |   |   |   |   |   interest4 <= 0
|   |   |   |   |   |   |   |   residence1 <= 0
|   |   |   |   |   |   |   |   |   school_accreditation1 <= 0
|   |   |   |   |   |   |   |   |   |   parent_salary <= 0.676667: 1 (36.0/5.0)
|   |   |   |   |   |   |   |   |   |   parent_salary > 0.676667
|   |   |   |   |   |   |   |   |   |   |   house_area <= 0.5: 1 (1.0)
|   |   |   |   |   |   |   |   |   |   |   house_area > 0.5: 0 (3.0)
|   |   |   |   |   |   |   |   |   school_accreditation1 > 0
|   |   |   |   |   |   |   |   |   |   house_area <= 0.634
|   |   |   |   |   |   |   |   |   |   |   parent_salary <= 0.538889: 1 (11.0)
|   |   |   |   |   |   |   |   |   |   |   parent_salary > 0.538889
|   |   |   |   |   |   |   |   |   |   |   |   parent_was_in_college1 <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   interest1 <= 0: 1 (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   interest1 > 0: 0 (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   parent_was_in_college1 > 0: 0 (4.0)
|   |   |   |   |   |   |   |   |   |   house_area > 0.634: 0 (6.0)
|   |   |   |   |   |   |   |   residence1 > 0
|   |   |   |   |   |   |   |   |   house_area <= 0.462: 0 (4.0)
|   |   |   |   |   |   |   |   |   house_area > 0.462
|   |   |   |   |   |   |   |   |   |   parent_age <= 52: 0 (2.0)
|   |   |   |   |   |   |   |   |   |   parent_age > 52: 1 (4.0/1.0)
|   |   |   |   |   |   |   interest4 > 0
|   |   |   |   |   |   |   |   residence1 <= 0
|   |   |   |   |   |   |   |   |   parent_age <= 48: 1 (2.0)
|   |   |   |   |   |   |   |   |   parent_age > 48
|   |   |   |   |   |   |   |   |   |   school_accreditation1 <= 0
|   |   |   |   |   |   |   |   |   |   |   parent_salary <= 0.587778: 1 (3.0)
|   |   |   |   |   |   |   |   |   |   |   parent_salary > 0.587778: 0 (6.0/1.0)
|   |   |   |   |   |   |   |   |   |   school_accreditation1 > 0: 0 (18.0/1.0)
|   |   |   |   |   |   |   |   residence1 > 0: 0 (13.0)
|   |   |   |   |   |   interest3 > 0: 0 (7.0)
|   |   |   |   |   interest2 > 0: 0 (24.0)
|   |   |   |   type_school1 > 0
|   |   |   |   |   school_accreditation1 <= 0: 0 (95.0/2.0)
|   |   |   |   |   school_accreditation1 > 0
|   |   |   |   |   |   residence1 <= 0
|   |   |   |   |   |   |   interest2 <= 0
|   |   |   |   |   |   |   |   interest4 <= 0: 0 (10.0)
|   |   |   |   |   |   |   |   interest4 > 0
|   |   |   |   |   |   |   |   |   parent_salary <= 0.606667: 1 (3.0)
|   |   |   |   |   |   |   |   |   parent_salary > 0.606667: 0 (2.0)
|   |   |   |   |   |   |   interest2 > 0: 1 (2.0)
|   |   |   |   |   |   residence1 > 0
|   |   |   |   |   |   |   parent_salary <= 0.503333
|   |   |   |   |   |   |   |   interest2 <= 0
|   |   |   |   |   |   |   |   |   house_area <= 0.665
|   |   |   |   |   |   |   |   |   |   parent_age <= 53
|   |   |   |   |   |   |   |   |   |   |   parent_salary <= 0.496667: 0 (4.0)
|   |   |   |   |   |   |   |   |   |   |   parent_salary > 0.496667: 1 (1.0)
|   |   |   |   |   |   |   |   |   |   parent_age > 53: 1 (5.0)
|   |   |   |   |   |   |   |   |   house_area > 0.665: 0 (4.0)
|   |   |   |   |   |   |   |   interest2 > 0: 0 (5.0)
|   |   |   |   |   |   |   parent_salary > 0.503333: 0 (41.0/1.0)
|   |   |   average_gradesB > 0
|   |   |   |   residence1 <= 0
|   |   |   |   |   house_area <= 0.635: 1 (59.0/6.0)
|   |   |   |   |   house_area > 0.635
|   |   |   |   |   |   parent_age <= 46: 1 (4.0)
|   |   |   |   |   |   parent_age > 46
|   |   |   |   |   |   |   interest2 <= 0: 0 (17.0/2.0)
|   |   |   |   |   |   |   interest2 > 0
|   |   |   |   |   |   |   |   type_school1 <= 0: 0 (1.0)
|   |   |   |   |   |   |   |   type_school1 > 0: 1 (2.0)
|   |   |   |   residence1 > 0
|   |   |   |   |   parent_was_in_college1 <= 0
|   |   |   |   |   |   school_accreditation1 <= 0
|   |   |   |   |   |   |   parent_salary <= 0.451111: 0 (4.0)
|   |   |   |   |   |   |   parent_salary > 0.451111
|   |   |   |   |   |   |   |   house_area <= 0.503: 0 (2.0)
|   |   |   |   |   |   |   |   house_area > 0.503: 1 (9.0)
|   |   |   |   |   |   school_accreditation1 > 0
|   |   |   |   |   |   |   interest3 <= 0: 0 (45.0/10.0)
|   |   |   |   |   |   |   interest3 > 0
|   |   |   |   |   |   |   |   house_area <= 0.675: 1 (5.0)
|   |   |   |   |   |   |   |   house_area > 0.675: 0 (2.0)
|   |   |   |   |   parent_was_in_college1 > 0: 0 (9.0)
average_gradesA > 0: 0 (123.0/2.0)

Number of Leaves  :     64

Size of the tree :  127

Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 480  20
         1  20 480
                                          
               Accuracy : 0.96            
                 95% CI : (0.9459, 0.9713)
    No Information Rate : 0.5             
    P-Value [Acc > NIR] : <2e-16          
                                          
                  Kappa : 0.92            
                                          
 Mcnemar's Test P-Value : 1               
                                          
            Sensitivity : 0.96            
            Specificity : 0.96            
         Pos Pred Value : 0.96            
         Neg Pred Value : 0.96            
             Prevalence : 0.50            
         Detection Rate : 0.48            
   Detection Prevalence : 0.50            
      Balanced Accuracy : 0.96            
                                          
       'Positive' Class : 0               
                                          

The gain ratio consistently favors unbalanced splits, as demonstrated by its selection of “Parent salary” as the root for all three trees even though it’s shown in the tree “average grades” as the root but the split point’s that all the value in one diraction . In this configuration, one partition is notably smaller than the others, and the feature exhibits a higher number of distinct values. Despite the fact that the node corresponding to “Parent age”, “parent was in collage” is not pure, the resulting trees exhibit impressive accuracy levels, all surpassing 94%

cart

library(caret)
library(rpart)
library(rpart.plot)



set.seed(1234) # Random seed
fold <- c(2, 3, 4)  # Values of xval (number of folds) to try

for (fold in fold) {
cat("fold"=fold)
trctrl <- trainControl(method = "cv", number = fold, savePredictions = TRUE)
dt_fit <- train(factor(will_go_to_college) ~ ., data = data, method = "rpart1SE", trControl = trctrl)

 # Plot decision tree
  rpart.plot(dt_fit$finalModel)
  
# Get predicted values
predictions <- predict(dt_fit, newdata = data)

# Create confusion matrix
confusion_matrix <- confusionMatrix(predictions, data$will_go_to_college)

# Print the confusion matrix
print(confusion_matrix)

#print each flod
pred <- dt_fit$pred
pred$equal <- ifelse(pred$pred == pred$obs, 1,0)
eachfold <- pred %>%                                        
  group_by(Resample) %>%                         
  summarise_at(vars(equal),                     
               list(Accuracy = mean))              
print(eachfold  )

  }
2
Warning: Cannot retrieve the data used to build the model (so cannot determine roundint and is.binary for the variables).
To silence this warning:
    Call rpart.plot with roundint=FALSE,
    or rebuild the rpart model with model=TRUE.
Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 431  53
         1  69 447
                                          
               Accuracy : 0.878           
                 95% CI : (0.8561, 0.8976)
    No Information Rate : 0.5             
    P-Value [Acc > NIR] : <2e-16          
                                          
                  Kappa : 0.756           
                                          
 Mcnemar's Test P-Value : 0.1745          
                                          
            Sensitivity : 0.8620          
            Specificity : 0.8940          
         Pos Pred Value : 0.8905          
         Neg Pred Value : 0.8663          
             Prevalence : 0.5000          
         Detection Rate : 0.4310          
   Detection Prevalence : 0.4840          
      Balanced Accuracy : 0.8780          
                                          
       'Positive' Class : 0               
                                          
3

Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 431  53
         1  69 447
                                          
               Accuracy : 0.878           
                 95% CI : (0.8561, 0.8976)
    No Information Rate : 0.5             
    P-Value [Acc > NIR] : <2e-16          
                                          
                  Kappa : 0.756           
                                          
 Mcnemar's Test P-Value : 0.1745          
                                          
            Sensitivity : 0.8620          
            Specificity : 0.8940          
         Pos Pred Value : 0.8905          
         Neg Pred Value : 0.8663          
             Prevalence : 0.5000          
         Detection Rate : 0.4310          
   Detection Prevalence : 0.4840          
      Balanced Accuracy : 0.8780          
                                          
       'Positive' Class : 0               
                                          
4

Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 431  53
         1  69 447
                                          
               Accuracy : 0.878           
                 95% CI : (0.8561, 0.8976)
    No Information Rate : 0.5             
    P-Value [Acc > NIR] : <2e-16          
                                          
                  Kappa : 0.756           
                                          
 Mcnemar's Test P-Value : 0.1745          
                                          
            Sensitivity : 0.8620          
            Specificity : 0.8940          
         Pos Pred Value : 0.8905          
         Neg Pred Value : 0.8663          
             Prevalence : 0.5000          
         Detection Rate : 0.4310          
   Detection Prevalence : 0.4840          
      Balanced Accuracy : 0.8780          
                                          
       'Positive' Class : 0               
                                          

averages grade exhibits the smallest Gini index binary split, signifying a substantial reduction in impurity. Hence, it is chosen as the splitting attribute. Conversely, attributes such as ‘type_school,’ ‘school_accreditation,’ ‘gender,’ ‘parent_age,’ and ‘parent_was_in_college’ yield minimal impurity reduction, leading to their exclusion from the tree. The dataset’s balanced class labels and marginal differences in accuracy across folds result in consistent tree structures, as evidenced by the identical trees in all folds. For further details, refer to the index. Overall, the model attains an 86% accuracy, emphasizing its effectiveness.

ID3

library(caret)
library(partykit)
library(dplyr)

fold <- c(4, 3, 2)  # Values of xval (number of folds) to try

for (fold in fold) {
  cat("fold =", fold, "\n")
  trctrl <- trainControl(method = "cv", number = fold, savePredictions = TRUE)
  
  id_fit <- train(factor(will_go_to_college) ~ ., data = data, method = "ctree", trControl = trctrl)
   print(id_fit$finalModel)
  # Get predicted values
  predictions <- predict(id_fit, newdata = data)
  
  # Create confusion matrix
  confusion_matrix <- confusionMatrix(predictions, data$will_go_to_college)
  
  # Print the confusion matrix
  print(confusion_matrix)
  
  # Print accuracy for each fold
  pred <- id_fit$pred
  pred$equal <- ifelse(pred$pred == pred$obs, 1, 0)
  eachfold <- pred %>%
    group_by(Resample) %>%
    summarise_at(vars(equal), list(Accuracy = mean))
  print(eachfold)

  # Plot decision tree
  plot(id_fit$finalModel, main = paste("Decision Tree (Fold", fold, ")"))
  
}
fold = 4 

     Conditional inference tree with 47 terminal nodes

Response:  .outcome 
Inputs:  type_school1, school_accreditation1, gender1, interest1, interest2, interest3, interest4, residence1, parent_age, parent_salary, house_area, average_grades+B, average_grades+C, average_gradesA, average_gradesB, parent_was_in_college1 
Number of observations:  1000 

1) parent_salary <= 0.4166667; criterion = 1, statistic = 226.057
  2) average_gradesA <= 0; criterion = 1, statistic = 104.378
    3) house_area <= 0.559; criterion = 1, statistic = 43.299
      4) parent_was_in_college1 <= 0; criterion = 0.568, statistic = 4.458
        5)*  weights = 120 
      4) parent_was_in_college1 > 0
        6)*  weights = 87 
    3) house_area > 0.559
      7) parent_was_in_college1 <= 0; criterion = 1, statistic = 30.227
        8) parent_salary <= 0.2966667; criterion = 1, statistic = 17.824
          9)*  weights = 18 
        8) parent_salary > 0.2966667
          10) interest2 <= 0; criterion = 0.083, statistic = 12.462
            11)*  weights = 19 
          10) interest2 > 0
            12)*  weights = 9 
      7) parent_was_in_college1 > 0
        13) average_gradesB <= 0; criterion = 0.748, statistic = 5.6
          14) type_school1 <= 0; criterion = 0.239, statistic = 20.682
            15)*  weights = 9 
          14) type_school1 > 0
            16)*  weights = 18 
        13) average_gradesB > 0
          17)*  weights = 28 
  2) average_gradesA > 0
    18) parent_age <= 54; criterion = 0.44, statistic = 3.84
      19)*  weights = 18 
    18) parent_age > 54
      20)*  weights = 7 
1) parent_salary > 0.4166667
  21) house_area <= 0.413; criterion = 1, statistic = 129.968
    22) type_school1 <= 0; criterion = 0.999, statistic = 19.583
      23) interest3 <= 0; criterion = 0.995, statistic = 12.818
        24) gender1 <= 0; criterion = 0.91, statistic = 7.586
          25)*  weights = 20 
        24) gender1 > 0
          26)*  weights = 13 
      23) interest3 > 0
        27)*  weights = 15 
    22) type_school1 > 0
      28) school_accreditation1 <= 0; criterion = 0.79, statistic = 5.963
        29)*  weights = 12 
      28) school_accreditation1 > 0
        30)*  weights = 35 
  21) house_area > 0.413
    31) average_gradesB <= 0; criterion = 1, statistic = 77.328
      32) type_school1 <= 0; criterion = 1, statistic = 52.367
        33) residence1 <= 0; criterion = 1, statistic = 17.463
          34) parent_salary <= 0.6611111; criterion = 1, statistic = 19.091
            35) average_grades+B <= 0; criterion = 0.965, statistic = 9.33
              36)*  weights = 12 
            35) average_grades+B > 0
              37) school_accreditation1 <= 0; criterion = 0.997, statistic = 13.937
                38) parent_salary <= 0.5711111; criterion = 0.455, statistic = 12.481
                  39)*  weights = 18 
                38) parent_salary > 0.5711111
                  40) house_area <= 0.615; criterion = 0.683, statistic = 7.331
                    41)*  weights = 15 
                  40) house_area > 0.615
                    42)*  weights = 14 
              37) school_accreditation1 > 0
                43) parent_salary <= 0.52; criterion = 0.987, statistic = 11.193
                  44)*  weights = 12 
                43) parent_salary > 0.52
                  45) parent_age <= 51; criterion = 0.844, statistic = 6.535
                    46) parent_age <= 49; criterion = 0.288, statistic = 3.174
                      47)*  weights = 11 
                    46) parent_age > 49
                      48)*  weights = 10 
                  45) parent_age > 51
                    49)*  weights = 12 
          34) parent_salary > 0.6611111
            50) house_area <= 0.496; criterion = 0.027, statistic = 1.625
              51)*  weights = 7 
            50) house_area > 0.496
              52)*  weights = 16 
        33) residence1 > 0
          53) interest4 <= 0; criterion = 0.02, statistic = 1.521
            54) interest2 <= 0; criterion = 0.169, statistic = 2.625
              55)*  weights = 16 
            54) interest2 > 0
              56)*  weights = 13 
          53) interest4 > 0
            57)*  weights = 14 
      32) type_school1 > 0
        58) school_accreditation1 <= 0; criterion = 0.997, statistic = 14.096
          59) interest4 <= 0; criterion = 0.185, statistic = 2.706
            60)*  weights = 86 
          59) interest4 > 0
            61) gender1 <= 0; criterion = 0.087, statistic = 2.163
              62) residence1 <= 0; criterion = 0.219, statistic = 2.865
                63)*  weights = 13 
              62) residence1 > 0
                64)*  weights = 18 
            61) gender1 > 0
              65)*  weights = 33 
        58) school_accreditation1 > 0
          66) gender1 <= 0; criterion = 0.445, statistic = 3.865
            67) parent_salary <= 0.5444444; criterion = 0.564, statistic = 4.44
              68)*  weights = 18 
            67) parent_salary > 0.5444444
              69) house_area <= 0.516; criterion = 0.102, statistic = 16.64
                70)*  weights = 7 
              69) house_area > 0.516
                71)*  weights = 20 
          66) gender1 > 0
            72) parent_age <= 54; criterion = 0.31, statistic = 3.27
              73) residence1 <= 0; criterion = 0.562, statistic = 4.429
                74)*  weights = 7 
              73) residence1 > 0
                75)*  weights = 31 
            72) parent_age > 54
              76)*  weights = 10 
    31) average_gradesB > 0
      77) residence1 <= 0; criterion = 1, statistic = 27.838
        78) house_area <= 0.633; criterion = 1, statistic = 27.626
          79) parent_was_in_college1 <= 0; criterion = 0.516, statistic = 4.195
            80)*  weights = 23 
          79) parent_was_in_college1 > 0
            81)*  weights = 36 
        78) house_area > 0.633
          82) parent_salary <= 0.5466667; criterion = 0.589, statistic = 4.568
            83)*  weights = 16 
          82) parent_salary > 0.5466667
            84)*  weights = 8 
      77) residence1 > 0
        85) parent_age <= 54; criterion = 0.938, statistic = 8.29
          86) house_area <= 0.562; criterion = 0.627, statistic = 4.783
            87) interest2 <= 0; criterion = 0.232, statistic = 4.312
              88) gender1 <= 0; criterion = 0.429, statistic = 6.609
                89)*  weights = 12 
              88) gender1 > 0
                90)*  weights = 13 
            87) interest2 > 0
              91)*  weights = 9 
          86) house_area > 0.562
            92)*  weights = 18 
        85) parent_age > 54
          93)*  weights = 24 
Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 450  51
         1  50 449
                                         
               Accuracy : 0.899          
                 95% CI : (0.8786, 0.917)
    No Information Rate : 0.5            
    P-Value [Acc > NIR] : <2e-16         
                                         
                  Kappa : 0.798          
                                         
 Mcnemar's Test P-Value : 1              
                                         
            Sensitivity : 0.9000         
            Specificity : 0.8980         
         Pos Pred Value : 0.8982         
         Neg Pred Value : 0.8998         
             Prevalence : 0.5000         
         Detection Rate : 0.4500         
   Detection Prevalence : 0.5010         
      Balanced Accuracy : 0.8990         
                                         
       'Positive' Class : 0              
                                         
fold = 3 

     Conditional inference tree with 47 terminal nodes

Response:  .outcome 
Inputs:  type_school1, school_accreditation1, gender1, interest1, interest2, interest3, interest4, residence1, parent_age, parent_salary, house_area, average_grades+B, average_grades+C, average_gradesA, average_gradesB, parent_was_in_college1 
Number of observations:  1000 

1) parent_salary <= 0.4166667; criterion = 1, statistic = 226.057
  2) average_gradesA <= 0; criterion = 1, statistic = 104.378
    3) house_area <= 0.559; criterion = 1, statistic = 43.299
      4) parent_was_in_college1 <= 0; criterion = 0.568, statistic = 4.458
        5)*  weights = 120 
      4) parent_was_in_college1 > 0
        6)*  weights = 87 
    3) house_area > 0.559
      7) parent_was_in_college1 <= 0; criterion = 1, statistic = 30.227
        8) parent_salary <= 0.2966667; criterion = 1, statistic = 17.824
          9)*  weights = 18 
        8) parent_salary > 0.2966667
          10) interest2 <= 0; criterion = 0.083, statistic = 12.462
            11)*  weights = 19 
          10) interest2 > 0
            12)*  weights = 9 
      7) parent_was_in_college1 > 0
        13) average_gradesB <= 0; criterion = 0.748, statistic = 5.6
          14) type_school1 <= 0; criterion = 0.239, statistic = 20.682
            15)*  weights = 9 
          14) type_school1 > 0
            16)*  weights = 18 
        13) average_gradesB > 0
          17)*  weights = 28 
  2) average_gradesA > 0
    18) parent_age <= 54; criterion = 0.44, statistic = 3.84
      19)*  weights = 18 
    18) parent_age > 54
      20)*  weights = 7 
1) parent_salary > 0.4166667
  21) house_area <= 0.413; criterion = 1, statistic = 129.968
    22) type_school1 <= 0; criterion = 0.999, statistic = 19.583
      23) interest3 <= 0; criterion = 0.995, statistic = 12.818
        24) gender1 <= 0; criterion = 0.91, statistic = 7.586
          25)*  weights = 20 
        24) gender1 > 0
          26)*  weights = 13 
      23) interest3 > 0
        27)*  weights = 15 
    22) type_school1 > 0
      28) school_accreditation1 <= 0; criterion = 0.79, statistic = 5.963
        29)*  weights = 12 
      28) school_accreditation1 > 0
        30)*  weights = 35 
  21) house_area > 0.413
    31) average_gradesB <= 0; criterion = 1, statistic = 77.328
      32) type_school1 <= 0; criterion = 1, statistic = 52.367
        33) residence1 <= 0; criterion = 1, statistic = 17.463
          34) parent_salary <= 0.6611111; criterion = 1, statistic = 19.091
            35) average_grades+B <= 0; criterion = 0.965, statistic = 9.33
              36)*  weights = 12 
            35) average_grades+B > 0
              37) school_accreditation1 <= 0; criterion = 0.997, statistic = 13.937
                38) parent_salary <= 0.5711111; criterion = 0.455, statistic = 12.481
                  39)*  weights = 18 
                38) parent_salary > 0.5711111
                  40) house_area <= 0.615; criterion = 0.683, statistic = 7.331
                    41)*  weights = 15 
                  40) house_area > 0.615
                    42)*  weights = 14 
              37) school_accreditation1 > 0
                43) parent_salary <= 0.52; criterion = 0.987, statistic = 11.193
                  44)*  weights = 12 
                43) parent_salary > 0.52
                  45) parent_age <= 51; criterion = 0.844, statistic = 6.535
                    46) parent_age <= 49; criterion = 0.288, statistic = 3.174
                      47)*  weights = 11 
                    46) parent_age > 49
                      48)*  weights = 10 
                  45) parent_age > 51
                    49)*  weights = 12 
          34) parent_salary > 0.6611111
            50) house_area <= 0.496; criterion = 0.027, statistic = 1.625
              51)*  weights = 7 
            50) house_area > 0.496
              52)*  weights = 16 
        33) residence1 > 0
          53) interest4 <= 0; criterion = 0.02, statistic = 1.521
            54) interest2 <= 0; criterion = 0.169, statistic = 2.625
              55)*  weights = 16 
            54) interest2 > 0
              56)*  weights = 13 
          53) interest4 > 0
            57)*  weights = 14 
      32) type_school1 > 0
        58) school_accreditation1 <= 0; criterion = 0.997, statistic = 14.096
          59) interest4 <= 0; criterion = 0.185, statistic = 2.706
            60)*  weights = 86 
          59) interest4 > 0
            61) gender1 <= 0; criterion = 0.087, statistic = 2.163
              62) residence1 <= 0; criterion = 0.219, statistic = 2.865
                63)*  weights = 13 
              62) residence1 > 0
                64)*  weights = 18 
            61) gender1 > 0
              65)*  weights = 33 
        58) school_accreditation1 > 0
          66) gender1 <= 0; criterion = 0.445, statistic = 3.865
            67) parent_salary <= 0.5444444; criterion = 0.564, statistic = 4.44
              68)*  weights = 18 
            67) parent_salary > 0.5444444
              69) house_area <= 0.516; criterion = 0.102, statistic = 16.64
                70)*  weights = 7 
              69) house_area > 0.516
                71)*  weights = 20 
          66) gender1 > 0
            72) parent_age <= 54; criterion = 0.31, statistic = 3.27
              73) residence1 <= 0; criterion = 0.562, statistic = 4.429
                74)*  weights = 7 
              73) residence1 > 0
                75)*  weights = 31 
            72) parent_age > 54
              76)*  weights = 10 
    31) average_gradesB > 0
      77) residence1 <= 0; criterion = 1, statistic = 27.838
        78) house_area <= 0.633; criterion = 1, statistic = 27.626
          79) parent_was_in_college1 <= 0; criterion = 0.516, statistic = 4.195
            80)*  weights = 23 
          79) parent_was_in_college1 > 0
            81)*  weights = 36 
        78) house_area > 0.633
          82) parent_salary <= 0.5466667; criterion = 0.589, statistic = 4.568
            83)*  weights = 16 
          82) parent_salary > 0.5466667
            84)*  weights = 8 
      77) residence1 > 0
        85) parent_age <= 54; criterion = 0.938, statistic = 8.29
          86) house_area <= 0.562; criterion = 0.627, statistic = 4.783
            87) interest2 <= 0; criterion = 0.232, statistic = 4.312
              88) gender1 <= 0; criterion = 0.429, statistic = 6.609
                89)*  weights = 12 
              88) gender1 > 0
                90)*  weights = 13 
            87) interest2 > 0
              91)*  weights = 9 
          86) house_area > 0.562
            92)*  weights = 18 
        85) parent_age > 54
          93)*  weights = 24 
Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 450  51
         1  50 449
                                         
               Accuracy : 0.899          
                 95% CI : (0.8786, 0.917)
    No Information Rate : 0.5            
    P-Value [Acc > NIR] : <2e-16         
                                         
                  Kappa : 0.798          
                                         
 Mcnemar's Test P-Value : 1              
                                         
            Sensitivity : 0.9000         
            Specificity : 0.8980         
         Pos Pred Value : 0.8982         
         Neg Pred Value : 0.8998         
             Prevalence : 0.5000         
         Detection Rate : 0.4500         
   Detection Prevalence : 0.5010         
      Balanced Accuracy : 0.8990         
                                         
       'Positive' Class : 0              
                                         
fold = 2 

     Conditional inference tree with 47 terminal nodes

Response:  .outcome 
Inputs:  type_school1, school_accreditation1, gender1, interest1, interest2, interest3, interest4, residence1, parent_age, parent_salary, house_area, average_grades+B, average_grades+C, average_gradesA, average_gradesB, parent_was_in_college1 
Number of observations:  1000 

1) parent_salary <= 0.4166667; criterion = 1, statistic = 226.057
  2) average_gradesA <= 0; criterion = 1, statistic = 104.378
    3) house_area <= 0.559; criterion = 1, statistic = 43.299
      4) parent_was_in_college1 <= 0; criterion = 0.568, statistic = 4.458
        5)*  weights = 120 
      4) parent_was_in_college1 > 0
        6)*  weights = 87 
    3) house_area > 0.559
      7) parent_was_in_college1 <= 0; criterion = 1, statistic = 30.227
        8) parent_salary <= 0.2966667; criterion = 1, statistic = 17.824
          9)*  weights = 18 
        8) parent_salary > 0.2966667
          10) interest2 <= 0; criterion = 0.083, statistic = 12.462
            11)*  weights = 19 
          10) interest2 > 0
            12)*  weights = 9 
      7) parent_was_in_college1 > 0
        13) average_gradesB <= 0; criterion = 0.748, statistic = 5.6
          14) type_school1 <= 0; criterion = 0.239, statistic = 20.682
            15)*  weights = 9 
          14) type_school1 > 0
            16)*  weights = 18 
        13) average_gradesB > 0
          17)*  weights = 28 
  2) average_gradesA > 0
    18) parent_age <= 54; criterion = 0.44, statistic = 3.84
      19)*  weights = 18 
    18) parent_age > 54
      20)*  weights = 7 
1) parent_salary > 0.4166667
  21) house_area <= 0.413; criterion = 1, statistic = 129.968
    22) type_school1 <= 0; criterion = 0.999, statistic = 19.583
      23) interest3 <= 0; criterion = 0.995, statistic = 12.818
        24) gender1 <= 0; criterion = 0.91, statistic = 7.586
          25)*  weights = 20 
        24) gender1 > 0
          26)*  weights = 13 
      23) interest3 > 0
        27)*  weights = 15 
    22) type_school1 > 0
      28) school_accreditation1 <= 0; criterion = 0.79, statistic = 5.963
        29)*  weights = 12 
      28) school_accreditation1 > 0
        30)*  weights = 35 
  21) house_area > 0.413
    31) average_gradesB <= 0; criterion = 1, statistic = 77.328
      32) type_school1 <= 0; criterion = 1, statistic = 52.367
        33) residence1 <= 0; criterion = 1, statistic = 17.463
          34) parent_salary <= 0.6611111; criterion = 1, statistic = 19.091
            35) average_grades+B <= 0; criterion = 0.965, statistic = 9.33
              36)*  weights = 12 
            35) average_grades+B > 0
              37) school_accreditation1 <= 0; criterion = 0.997, statistic = 13.937
                38) parent_salary <= 0.5711111; criterion = 0.455, statistic = 12.481
                  39)*  weights = 18 
                38) parent_salary > 0.5711111
                  40) house_area <= 0.615; criterion = 0.683, statistic = 7.331
                    41)*  weights = 15 
                  40) house_area > 0.615
                    42)*  weights = 14 
              37) school_accreditation1 > 0
                43) parent_salary <= 0.52; criterion = 0.987, statistic = 11.193
                  44)*  weights = 12 
                43) parent_salary > 0.52
                  45) parent_age <= 51; criterion = 0.844, statistic = 6.535
                    46) parent_age <= 49; criterion = 0.288, statistic = 3.174
                      47)*  weights = 11 
                    46) parent_age > 49
                      48)*  weights = 10 
                  45) parent_age > 51
                    49)*  weights = 12 
          34) parent_salary > 0.6611111
            50) house_area <= 0.496; criterion = 0.027, statistic = 1.625
              51)*  weights = 7 
            50) house_area > 0.496
              52)*  weights = 16 
        33) residence1 > 0
          53) interest4 <= 0; criterion = 0.02, statistic = 1.521
            54) interest2 <= 0; criterion = 0.169, statistic = 2.625
              55)*  weights = 16 
            54) interest2 > 0
              56)*  weights = 13 
          53) interest4 > 0
            57)*  weights = 14 
      32) type_school1 > 0
        58) school_accreditation1 <= 0; criterion = 0.997, statistic = 14.096
          59) interest4 <= 0; criterion = 0.185, statistic = 2.706
            60)*  weights = 86 
          59) interest4 > 0
            61) gender1 <= 0; criterion = 0.087, statistic = 2.163
              62) residence1 <= 0; criterion = 0.219, statistic = 2.865
                63)*  weights = 13 
              62) residence1 > 0
                64)*  weights = 18 
            61) gender1 > 0
              65)*  weights = 33 
        58) school_accreditation1 > 0
          66) gender1 <= 0; criterion = 0.445, statistic = 3.865
            67) parent_salary <= 0.5444444; criterion = 0.564, statistic = 4.44
              68)*  weights = 18 
            67) parent_salary > 0.5444444
              69) house_area <= 0.516; criterion = 0.102, statistic = 16.64
                70)*  weights = 7 
              69) house_area > 0.516
                71)*  weights = 20 
          66) gender1 > 0
            72) parent_age <= 54; criterion = 0.31, statistic = 3.27
              73) residence1 <= 0; criterion = 0.562, statistic = 4.429
                74)*  weights = 7 
              73) residence1 > 0
                75)*  weights = 31 
            72) parent_age > 54
              76)*  weights = 10 
    31) average_gradesB > 0
      77) residence1 <= 0; criterion = 1, statistic = 27.838
        78) house_area <= 0.633; criterion = 1, statistic = 27.626
          79) parent_was_in_college1 <= 0; criterion = 0.516, statistic = 4.195
            80)*  weights = 23 
          79) parent_was_in_college1 > 0
            81)*  weights = 36 
        78) house_area > 0.633
          82) parent_salary <= 0.5466667; criterion = 0.589, statistic = 4.568
            83)*  weights = 16 
          82) parent_salary > 0.5466667
            84)*  weights = 8 
      77) residence1 > 0
        85) parent_age <= 54; criterion = 0.938, statistic = 8.29
          86) house_area <= 0.562; criterion = 0.627, statistic = 4.783
            87) interest2 <= 0; criterion = 0.232, statistic = 4.312
              88) gender1 <= 0; criterion = 0.429, statistic = 6.609
                89)*  weights = 12 
              88) gender1 > 0
                90)*  weights = 13 
            87) interest2 > 0
              91)*  weights = 9 
          86) house_area > 0.562
            92)*  weights = 18 
        85) parent_age > 54
          93)*  weights = 24 
Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 450  51
         1  50 449
                                         
               Accuracy : 0.899          
                 95% CI : (0.8786, 0.917)
    No Information Rate : 0.5            
    P-Value [Acc > NIR] : <2e-16         
                                         
                  Kappa : 0.798          
                                         
 Mcnemar's Test P-Value : 1              
                                         
            Sensitivity : 0.9000         
            Specificity : 0.8980         
         Pos Pred Value : 0.8982         
         Neg Pred Value : 0.8998         
             Prevalence : 0.5000         
         Detection Rate : 0.4500         
   Detection Prevalence : 0.5010         
      Balanced Accuracy : 0.8990         
                                         
       'Positive' Class : 0              
                                         

Additional insights reveal that attributes such as school accreditation, parent was in collage contribute to high impurity. In contrast, Parent salary is chosen as the root due to its high purity. Given the balanced class labels in our dataset and minimal variations in accuracy across folds, the result yields consistent tree structures, with only two distinct trees observed for all folds. For further details, please refer to the index. The overall accuracy consistently surpasses 86%, affirming the model’s efficacy

final analysis

The C4.5 model emerged as the top-performing evaluation model, achieving an impressive accuracy rate of 94% to 97%. It was followed by the ID3 model, which demonstrated slightly lower accuracy ranging from 86% to 89%. Lastly, the cart model exhibited an accuracy rate of 86%.

the C4.5 gave better result than ID3 and Cart because they both are biased to multivalued where C4.5 normalized parent salary and house area which are multivalue attributes

C4.5 and ID3 models, the parent’s salary served as the root feature, indicating that the financial circumstances of the student are a crucial factor for contemporary universities.

index

all trees of C4.5

library(caret)
library(rpart)
library(dplyr)
library(rpart.plot)

folds <- c(2, 3, 4)  # Values of xval (number of folds) to try

for(folds in folds){ 
  cat("fold =", fold_val, "\n")
for (fold_val in 1:folds) {
 
  
  trctrl <- trainControl(method = "cv", number = fold_val, savePredictions = TRUE)
  c45_fit <- train(factor(will_go_to_college) ~ ., data = data, method = "J48", trControl = trctrl)
  
   plot(c45_fit$finalModel, main = paste("Decision Tree - Fold", fold_val))
}
  # Get predicted values
  predictions <- predict(c45_fit, newdata = data)
  
  # Create confusion matrix
  confusion_matrix <- confusionMatrix(predictions, data$will_go_to_college)
  
  # Print the confusion matrix
  print(confusion_matrix)
  
  # Print accuracy for each fold
  pred <- c45_fit$pred
  pred$equal <- ifelse(pred$pred == pred$obs, 1, 0)
  eachfold <- pred %>%
    group_by(Resample) %>%
    summarise_at(vars(equal),
                 list(Accuracy = mean))
  print(eachfold)
  
  # Plot decision tree for each fold
 

}
fold = 4 
Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 475  29
         1  25 471
                                          
               Accuracy : 0.946           
                 95% CI : (0.9301, 0.9592)
    No Information Rate : 0.5             
    P-Value [Acc > NIR] : <2e-16          
                                          
                  Kappa : 0.892           
                                          
 Mcnemar's Test P-Value : 0.6831          
                                          
            Sensitivity : 0.9500          
            Specificity : 0.9420          
         Pos Pred Value : 0.9425          
         Neg Pred Value : 0.9496          
             Prevalence : 0.5000          
         Detection Rate : 0.4750          
   Detection Prevalence : 0.5040          
      Balanced Accuracy : 0.9460          
                                          
       'Positive' Class : 0               
                                          
fold = 2 
Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 480  20
         1  20 480
                                          
               Accuracy : 0.96            
                 95% CI : (0.9459, 0.9713)
    No Information Rate : 0.5             
    P-Value [Acc > NIR] : <2e-16          
                                          
                  Kappa : 0.92            
                                          
 Mcnemar's Test P-Value : 1               
                                          
            Sensitivity : 0.96            
            Specificity : 0.96            
         Pos Pred Value : 0.96            
         Neg Pred Value : 0.96            
             Prevalence : 0.50            
         Detection Rate : 0.48            
   Detection Prevalence : 0.50            
      Balanced Accuracy : 0.96            
                                          
       'Positive' Class : 0               
                                          
fold = 3 
Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 487  13
         1  13 487
                                          
               Accuracy : 0.974           
                 95% CI : (0.9621, 0.9829)
    No Information Rate : 0.5             
    P-Value [Acc > NIR] : <2e-16          
                                          
                  Kappa : 0.948           
                                          
 Mcnemar's Test P-Value : 1               
                                          
            Sensitivity : 0.974           
            Specificity : 0.974           
         Pos Pred Value : 0.974           
         Neg Pred Value : 0.974           
             Prevalence : 0.500           
         Detection Rate : 0.487           
   Detection Prevalence : 0.500           
      Balanced Accuracy : 0.974           
                                          
       'Positive' Class : 0               
                                          

all trees of ID3

library(caret)
library(partykit)
library(dplyr)

fold <- c(4, 3, 2)  # Values of xval (number of folds) to try

for (fold in fold) {
   cat("fold =", fold, "\n")
  for(i in 1:fold){
  trctrl <- trainControl(method = "cv", number = fold, savePredictions = TRUE)
  
  id_fit <- train(factor(will_go_to_college) ~ ., data = data, method = "ctree", trControl = trctrl, subset = trctrl$indexes[[i]])
  
    plot(id_fit$finalModel, main = paste("Decision Tree (Fold", fold,"-", i, ")"))
}
   
  # Get predicted values
  predictions <- predict(id_fit, newdata = data)
  
  # Create confusion matrix
  confusion_matrix <- confusionMatrix(predictions, data$will_go_to_college)
  
  # Print the confusion matrix
  print(confusion_matrix)
  
  # Print accuracy for each fold
  pred <- id_fit$pred
  pred$equal <- ifelse(pred$pred == pred$obs, 1, 0)
  eachfold <- pred %>%
    group_by(Resample) %>%
    summarise_at(vars(equal), list(Accuracy = mean))
  print(eachfold)

  # Plot decision tree


}
fold = 4 
Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 450  51
         1  50 449
                                         
               Accuracy : 0.899          
                 95% CI : (0.8786, 0.917)
    No Information Rate : 0.5            
    P-Value [Acc > NIR] : <2e-16         
                                         
                  Kappa : 0.798          
                                         
 Mcnemar's Test P-Value : 1              
                                         
            Sensitivity : 0.9000         
            Specificity : 0.8980         
         Pos Pred Value : 0.8982         
         Neg Pred Value : 0.8998         
             Prevalence : 0.5000         
         Detection Rate : 0.4500         
   Detection Prevalence : 0.5010         
      Balanced Accuracy : 0.8990         
                                         
       'Positive' Class : 0              
                                         
fold = 3 
Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 450  51
         1  50 449
                                         
               Accuracy : 0.899          
                 95% CI : (0.8786, 0.917)
    No Information Rate : 0.5            
    P-Value [Acc > NIR] : <2e-16         
                                         
                  Kappa : 0.798          
                                         
 Mcnemar's Test P-Value : 1              
                                         
            Sensitivity : 0.9000         
            Specificity : 0.8980         
         Pos Pred Value : 0.8982         
         Neg Pred Value : 0.8998         
             Prevalence : 0.5000         
         Detection Rate : 0.4500         
   Detection Prevalence : 0.5010         
      Balanced Accuracy : 0.8990         
                                         
       'Positive' Class : 0              
                                         
fold = 2 
Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 445  51
         1  55 449
                                          
               Accuracy : 0.894           
                 95% CI : (0.8732, 0.9124)
    No Information Rate : 0.5             
    P-Value [Acc > NIR] : <2e-16          
                                          
                  Kappa : 0.788           
                                          
 Mcnemar's Test P-Value : 0.7708          
                                          
            Sensitivity : 0.8900          
            Specificity : 0.8980          
         Pos Pred Value : 0.8972          
         Neg Pred Value : 0.8909          
             Prevalence : 0.5000          
         Detection Rate : 0.4450          
   Detection Prevalence : 0.4960          
      Balanced Accuracy : 0.8940          
                                          
       'Positive' Class : 0               
                                          

all trees of Cart

library(caret)
library(rpart)
library(rpart.plot)

set.seed(123) # Random seed
fold <- c(2, 3, 4)  # Values of xval (number of folds) to try

for (fold in fold) {
  cat("fold"=fold)
  for(i in 1:fold){

trctrl <- trainControl(method = "cv", number = fold, savePredictions = TRUE)
dt_fit <- train(factor(will_go_to_college) ~ ., data = data, method = "rpart1SE", trControl = trctrl)

 # Plot decision tree
  cat("Decision Tree - Fold", i, ":\n")
  rpart.plot(dt_fit$finalModel)
  
}
# Get predicted values
predictions <- predict(dt_fit, newdata = data)

# Create confusion matrix
confusion_matrix <- confusionMatrix(predictions, data$will_go_to_college)

# Print the confusion matrix
print(confusion_matrix)

#print each flod
pred <- dt_fit$pred
pred$equal <- ifelse(pred$pred == pred$obs, 1,0)
eachfold <- pred %>%                                        
  group_by(Resample) %>%                         
  summarise_at(vars(equal),                     
               list(Accuracy = mean))              
print(eachfold  )

  }
2Decision Tree - Fold 1 :
Warning: Cannot retrieve the data used to build the model (so cannot determine roundint and is.binary for the variables).
To silence this warning:
    Call rpart.plot with roundint=FALSE,
    or rebuild the rpart model with model=TRUE.
Decision Tree - Fold 2 :

Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 431  53
         1  69 447
                                          
               Accuracy : 0.878           
                 95% CI : (0.8561, 0.8976)
    No Information Rate : 0.5             
    P-Value [Acc > NIR] : <2e-16          
                                          
                  Kappa : 0.756           
                                          
 Mcnemar's Test P-Value : 0.1745          
                                          
            Sensitivity : 0.8620          
            Specificity : 0.8940          
         Pos Pred Value : 0.8905          
         Neg Pred Value : 0.8663          
             Prevalence : 0.5000          
         Detection Rate : 0.4310          
   Detection Prevalence : 0.4840          
      Balanced Accuracy : 0.8780          
                                          
       'Positive' Class : 0               
                                          
3Decision Tree - Fold 1 :

Decision Tree - Fold 2 :

Decision Tree - Fold 3 :

Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 431  53
         1  69 447
                                          
               Accuracy : 0.878           
                 95% CI : (0.8561, 0.8976)
    No Information Rate : 0.5             
    P-Value [Acc > NIR] : <2e-16          
                                          
                  Kappa : 0.756           
                                          
 Mcnemar's Test P-Value : 0.1745          
                                          
            Sensitivity : 0.8620          
            Specificity : 0.8940          
         Pos Pred Value : 0.8905          
         Neg Pred Value : 0.8663          
             Prevalence : 0.5000          
         Detection Rate : 0.4310          
   Detection Prevalence : 0.4840          
      Balanced Accuracy : 0.8780          
                                          
       'Positive' Class : 0               
                                          
4Decision Tree - Fold 1 :

Decision Tree - Fold 2 :

Decision Tree - Fold 3 :

Decision Tree - Fold 4 :

Confusion Matrix and Statistics

          Reference
Prediction   0   1
         0 431  53
         1  69 447
                                          
               Accuracy : 0.878           
                 95% CI : (0.8561, 0.8976)
    No Information Rate : 0.5             
    P-Value [Acc > NIR] : <2e-16          
                                          
                  Kappa : 0.756           
                                          
 Mcnemar's Test P-Value : 0.1745          
                                          
            Sensitivity : 0.8620          
            Specificity : 0.8940          
         Pos Pred Value : 0.8905          
         Neg Pred Value : 0.8663          
             Prevalence : 0.5000          
         Detection Rate : 0.4310          
   Detection Prevalence : 0.4840          
      Balanced Accuracy : 0.8780          
                                          
       'Positive' Class : 0               
                                          

Clustering Analysis:

In this analysis, we apply K-means clustering to the dataset using different values of K. K-means clustering is an unsupervised learning algorithm that partitions the data into K clusters based on similarity. We will explore three different values of K and evaluate the clustering results using various metrics.

Removing the class label and preparing the dataset for Clustering

 
original_data <- Preprocessed_dataset

# Remove any non-numeric attributes
numeric_data <- original_data[, sapply(original_data, is.numeric)]

# Remove the class label 'will_go_to_college'
numeric_data <- numeric_data[, !(names(numeric_data) == 'will_go_to_college')]


# Print the dataset "numeric_data" to make sure it's prepared for clustering
print(numeric_data)

# Scaling the dataset
# numeric_data <- scale(numeric_data)

 

Now, the ‘numeric_dataset’ dataset contains only numeric attributes without the class label, which makes it ready for the clustering process.

K=2

# k-means clustering set a seed for random number generation to make the results reproducible 
set.seed(8953)

# run kmeans clustering to find 2 clusters
kmeans.result <- kmeans(numeric_data, 2)

# visualize clustering
library(factoextra)
fviz_cluster(kmeans.result, data = numeric_data)


# print the clustering result
print(kmeans.result)
K-means clustering with 2 clusters of sizes 531, 469

Cluster means:
  type_school school_accreditation    gender interest residence parent_age parent_salary
1   0.5856874            0.4067797 0.5235405 2.001883 0.3163842   49.67985     0.5219000
2   0.6353945            0.5650320 0.4413646 2.296375 0.7910448   55.07036     0.4471476
  house_area parent_was_in_college
1  0.5351620              0.700565
2  0.5564648              0.315565

Clustering vector:
   [1] 2 2 1 1 2 1 1 2 1 1 2 1 1 2 1 2 1 1 1 1 1 2 1 2 2 1 2 2 1 1 1 2 2 1 1 2 2 1 2 2 1 2 2 1 1
  [46] 1 1 2 2 2 1 2 1 1 1 2 2 1 1 2 1 1 1 1 2 2 1 1 1 2 2 1 1 2 2 2 2 2 1 1 2 1 2 1 2 2 2 1 1 2
  [91] 2 2 2 1 1 1 1 2 1 1 1 2 1 1 1 2 1 2 2 2 1 1 1 1 1 1 1 2 2 2 1 1 1 1 2 2 1 1 1 2 2 1 2 1 1
 [136] 1 2 1 2 2 2 2 1 1 2 1 1 2 1 1 1 1 2 1 2 1 2 1 2 2 2 1 2 2 1 2 2 2 1 1 2 1 2 1 2 1 1 1 1 1
 [181] 2 1 2 1 1 2 2 2 2 2 2 1 1 2 2 2 1 2 2 2 2 2 2 2 1 2 2 1 2 1 1 1 1 2 2 1 2 1 1 1 2 1 2 1 2
 [226] 1 2 1 2 1 2 2 2 1 1 2 2 1 1 2 2 1 1 1 2 2 1 1 1 2 2 1 1 2 1 1 1 2 1 2 2 2 1 1 2 1 2 1 2 1
 [271] 1 1 1 2 1 1 1 2 1 2 1 1 2 1 1 2 2 2 1 1 2 1 2 1 1 2 1 1 1 2 1 2 1 1 1 1 1 2 1 2 1 2 2 2 2
 [316] 2 1 2 2 1 2 2 2 1 1 2 1 2 1 2 2 1 1 2 2 2 1 1 2 1 1 1 1 1 1 1 1 2 1 2 1 1 1 1 2 1 1 2 1 1
 [361] 1 1 1 1 1 1 1 1 1 2 2 2 2 2 1 1 2 1 2 2 1 2 1 2 2 1 2 2 1 2 1 2 1 1 1 2 1 1 1 1 2 2 1 2 1
 [406] 2 2 1 2 1 1 2 1 2 1 2 2 1 2 2 1 1 2 2 2 2 1 2 2 2 1 1 1 2 2 1 2 1 2 1 2 1 2 2 2 1 1 1 1 2
 [451] 1 1 1 2 1 2 1 1 2 1 1 2 2 1 1 1 1 1 2 1 2 1 2 2 1 1 1 1 1 1 2 1 1 1 2 1 2 2 1 1 1 1 1 2 1
 [496] 2 1 2 1 2 2 2 2 1 2 2 2 1 2 2 1 1 1 2 2 2 2 1 1 2 1 2 2 1 1 1 2 1 1 1 1 2 1 1 2 2 1 1 1 1
 [541] 1 1 1 2 1 1 1 1 2 2 1 2 2 2 2 1 1 1 1 1 1 2 2 1 2 1 2 2 1 2 2 2 2 1 1 2 2 1 1 2 1 1 2 1 2
 [586] 2 1 1 1 2 1 2 2 2 1 1 2 2 1 2 2 2 1 2 2 1 2 1 2 1 1 1 1 1 2 2 1 1 2 2 1 1 2 1 2 2 1 1 2 2
 [631] 1 1 2 1 2 2 1 1 1 2 1 2 1 2 2 2 2 1 1 2 2 2 2 1 1 1 2 2 2 1 2 2 1 2 1 1 1 1 2 1 1 1 1 2 2
 [676] 1 2 2 2 2 1 2 1 2 2 2 1 1 1 2 1 1 1 1 2 1 1 2 1 1 2 1 2 1 1 1 1 2 1 2 1 1 2 1 1 2 2 2 1 1
 [721] 1 2 2 1 2 2 1 1 2 1 2 1 2 1 1 1 1 2 1 2 1 1 1 1 2 1 2 2 1 2 1 1 2 2 1 1 1 1 2 1 2 2 1 2 2
 [766] 2 2 2 1 2 2 2 1 1 1 1 2 1 2 1 1 2 2 2 2 2 2 1 1 2 1 2 2 2 2 1 1 2 2 1 1 1 2 1 2 2 1 2 2 1
 [811] 1 2 1 1 1 1 1 1 1 2 2 2 2 1 2 1 1 2 1 2 1 1 2 2 1 1 1 2 1 1 2 1 2 2 2 1 1 2 2 1 1 2 1 2 2
 [856] 2 1 2 1 1 2 2 2 2 1 2 2 1 1 2 2 1 1 2 2 1 2 2 1 2 1 2 2 1 2 2 1 2 2 1 1 2 1 2 1 2 2 1 1 1
 [901] 1 1 2 2 2 1 1 1 2 1 2 2 1 2 2 2 1 1 2 1 1 2 2 1 1 1 2 2 2 2 1 1 2 2 1 1 2 2 1 2 2 2 2 1 1
 [946] 1 2 2 2 2 2 1 1 1 1 1 2 2 1 2 1 1 1 2 2 1 1 1 1 2 2 2 1 2 2 1 2 1 2 1 1 1 1 1 2 2 2 1 2 1
 [991] 2 1 2 2 1 1 1 1 2 1

Within cluster sum of squares by cluster:
[1] 5022.712 3646.347
 (between_SS / total_SS =  45.9 %)

Available components:

[1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss" "betweenss"   
[7] "size"         "iter"         "ifault"      

The Silhouette coefficient

#average for each cluster 
avg_sil <- silhouette(kmeans.result$cluster, dist(numeric_data)) 

#k-means clustering with estimating k and initializations 
fviz_silhouette(avg_sil)
NA

The total within-cluster sum of squares

# Calculate total within-cluster sum of squares
total_withinss <- kmeans.result$tot.withinss
cat("Total Within-Cluster Sum of Squares:", sum(total_withinss), "\n")
Total Within-Cluster Sum of Squares: 8669.059 
true_labels <- c(1, 1, 2, 1, 2, 2, 3, 3, 4, 4)  # Adjust based on your actual true labels

cluster_assignments <- kmeans.result$cluster
 

BCubed recall and precision


# Calculate BCubed precision
precision <- 0
for (i in unique(true_labels)) {
  cluster_indices <- which(true_labels == i)
  precision <- precision + sum((table(cluster_assignments[cluster_indices]) * (table(cluster_assignments[cluster_indices]) - 1)) / sum(table(cluster_assignments[cluster_indices])))
}
precision <- precision / sum(table(cluster_assignments))

# Calculate BCubed recall
recall <- 0
for (j in unique(cluster_assignments)) {
  cluster_indices <- which(cluster_assignments == j)
  recall <- recall + sum((table(true_labels[cluster_indices]) * (table(true_labels[cluster_indices]) - 1)) / sum(table(true_labels[cluster_indices])))
}
recall <- recall / sum(table(true_labels))

cat("BCubed Precision:", precision, "\n")
BCubed Precision: 0.002333333 
cat("BCubed Recall:", recall, "\n")
BCubed Recall: 0.1166667 

K=4

# k-means clustering set a seed for random number generation to make the results reproducible 
set.seed(8953)

# run kmeans clustering to find 4 clusters
kmeans.result <- kmeans(numeric_data, 4)

# visualize clustering
library(factoextra)
fviz_cluster(kmeans.result, data = numeric_data)


# print the clustering result
print(kmeans.result)
K-means clustering with 4 clusters of sizes 167, 66, 293, 474

Cluster means:
  type_school school_accreditation    gender interest residence parent_age parent_salary
1   0.6467066            0.5688623 0.3832335 2.245509 0.8323353   55.70060     0.4286427
2   0.6818182            0.6515152 0.5151515 2.181818 1.0000000   59.21212     0.3625589
3   0.5255973            0.3549488 0.5631399 1.928328 0.1979522   48.11604     0.5310315
4   0.6371308            0.5042194 0.4683544 2.227848 0.5822785   52.53165     0.4973347
  house_area parent_was_in_college
1  0.5677605             0.2455090
2  0.5229545             0.1060606
3  0.5202048             0.8122867
4  0.5557004             0.4936709

Clustering vector:
   [1] 1 1 3 3 1 3 4 4 4 3 1 3 3 4 4 4 3 3 3 3 4 1 4 2 4 4 1 4 4 3 3 4 2 4 4 4 1 3 4 4 3 4 4 4 3
  [46] 3 4 1 4 4 3 1 4 4 4 1 1 3 3 1 3 3 4 3 1 4 4 4 4 4 4 3 3 1 4 1 1 4 3 4 4 3 2 4 1 1 1 4 4 4
  [91] 1 4 2 4 3 3 3 4 4 4 4 1 4 4 4 4 3 4 2 1 4 4 4 4 3 3 3 4 2 1 3 3 4 3 1 4 3 3 3 4 1 3 4 3 3
 [136] 3 4 3 4 4 4 2 3 3 4 3 3 1 3 3 3 3 2 4 1 3 1 4 1 4 4 4 4 1 3 4 4 2 3 3 1 3 2 3 4 3 4 4 4 4
 [181] 4 4 1 3 3 4 1 4 4 4 4 3 4 1 4 1 3 4 1 4 1 2 4 1 4 4 2 3 4 3 3 3 3 4 1 4 4 4 3 4 2 4 1 3 4
 [226] 4 4 3 4 4 4 4 4 4 4 2 1 4 4 1 1 4 3 4 4 4 3 4 3 1 2 3 3 1 3 3 4 4 3 4 2 4 3 3 4 3 1 3 4 3
 [271] 3 4 3 4 4 3 3 4 3 1 4 4 1 3 3 4 1 4 4 4 2 4 2 4 3 1 3 4 3 4 4 4 3 3 4 3 3 4 3 1 3 4 4 1 4
 [316] 4 4 1 1 3 2 2 1 3 3 1 3 4 3 4 4 4 4 2 4 4 3 4 4 3 4 4 3 4 4 3 4 1 4 4 4 4 4 3 1 3 4 1 4 3
 [361] 3 3 3 3 4 3 3 3 3 1 1 1 2 4 4 4 1 3 4 4 4 4 3 1 4 4 1 2 3 1 4 2 3 3 3 2 4 3 4 3 4 1 3 4 3
 [406] 4 4 4 1 3 4 1 4 2 3 1 4 4 4 4 3 3 1 1 2 1 3 1 1 4 3 4 3 1 1 3 4 3 4 4 4 3 2 1 4 3 3 3 4 4
 [451] 4 4 4 4 3 4 4 4 4 4 4 2 2 3 4 3 3 4 4 4 4 3 4 4 4 4 4 3 4 3 1 3 3 3 2 4 4 1 4 4 3 4 3 4 3
 [496] 4 3 2 3 4 4 4 4 4 4 1 1 3 1 4 3 3 4 2 1 4 1 3 3 1 4 2 1 4 3 4 4 3 3 3 3 1 4 3 2 4 3 3 3 4
 [541] 3 4 4 4 3 4 3 4 1 1 4 2 4 1 4 3 4 3 4 3 3 4 4 3 4 4 4 2 4 4 1 1 1 3 4 1 4 3 3 4 4 4 4 3 4
 [586] 1 4 4 4 4 3 1 4 4 4 3 1 4 4 1 1 1 4 4 4 3 1 4 4 3 4 3 4 3 2 1 3 4 2 4 4 4 1 3 1 2 3 3 2 4
 [631] 4 3 2 4 4 1 4 3 4 2 3 2 4 4 4 1 4 4 4 4 1 4 2 4 4 3 4 4 4 3 2 4 3 2 4 4 3 3 1 4 4 3 3 1 1
 [676] 3 1 2 1 4 4 1 3 4 1 2 4 4 4 4 4 3 3 3 4 4 4 4 3 3 4 4 4 3 4 4 4 1 3 4 3 4 1 3 3 4 1 2 3 4
 [721] 3 2 4 3 1 1 3 3 4 3 4 4 4 3 3 3 4 4 4 4 3 3 3 3 1 4 1 4 3 4 3 4 4 1 4 3 3 3 4 4 1 4 4 4 1
 [766] 4 2 2 3 4 4 4 3 4 3 3 4 3 2 4 4 4 4 4 4 4 4 4 4 4 4 1 4 1 4 3 3 1 4 3 3 3 4 3 4 4 4 4 4 4
 [811] 3 1 3 3 3 3 3 4 3 4 4 4 1 4 2 4 4 1 4 2 3 3 1 1 3 4 4 1 3 3 4 4 1 1 1 4 4 1 1 3 3 1 3 4 2
 [856] 4 3 4 3 3 4 4 4 2 3 4 2 4 3 4 1 4 3 4 4 4 4 4 4 4 3 2 4 3 2 1 4 4 4 3 3 1 4 4 3 1 4 3 4 3
 [901] 4 4 4 2 4 3 4 4 2 4 4 1 4 4 2 4 4 3 4 3 3 1 1 4 4 4 1 4 1 1 3 4 1 1 3 4 4 1 4 1 1 1 1 4 4
 [946] 3 4 4 4 4 2 4 4 4 3 4 1 1 3 1 4 4 3 1 1 3 3 4 4 4 1 1 4 4 4 3 1 4 1 4 4 4 3 3 1 4 2 3 4 3
 [991] 4 4 4 4 4 3 4 3 4 3

Within cluster sum of squares by cluster:
[1]  640.8068  291.1379 2380.6791 2338.2145
 (between_SS / total_SS =  64.7 %)

Available components:

[1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss" "betweenss"   
[7] "size"         "iter"         "ifault"      

The Silhouette coefficient

#average for each cluster 
avg_sil <- silhouette(kmeans.result$cluster, dist(numeric_data)) 

#k-means clustering with estimating k and initializations 
fviz_silhouette(avg_sil)
NA

The total within-cluster sum of squares

# Calculate total within-cluster sum of squares
total_withinss <- kmeans.result$tot.withinss
cat("Total Within-Cluster Sum of Squares:", sum(total_withinss), "\n")
Total Within-Cluster Sum of Squares: 5650.838 
true_labels <- c(1, 1, 2, 1, 2, 2, 3, 3, 4, 4)  # Adjust based on your actual true labels

cluster_assignments <- kmeans.result$cluster
 

BCubed recall and precision


# Calculate BCubed precision
precision <- 0
for (i in unique(true_labels)) {
  cluster_indices <- which(true_labels == i)
  precision <- precision + sum((table(cluster_assignments[cluster_indices]) * (table(cluster_assignments[cluster_indices]) - 1)) / sum(table(cluster_assignments[cluster_indices])))
}
precision <- precision / sum(table(cluster_assignments))

# Calculate BCubed recall
recall <- 0
for (j in unique(cluster_assignments)) {
  cluster_indices <- which(cluster_assignments == j)
  recall <- recall + sum((table(true_labels[cluster_indices]) * (table(true_labels[cluster_indices]) - 1)) / sum(table(true_labels[cluster_indices])))
}
recall <- recall / sum(table(true_labels))

cat("BCubed Precision:", precision, "\n")
BCubed Precision: 0.002333333 
cat("BCubed Recall:", recall, "\n")
BCubed Recall: 0.1833333 

K=6

# k-means clustering set a seed for random number generation to make the results reproducible 
set.seed(8953)

# run kmeans clustering to find 6 clusters
kmeans.result <- kmeans(numeric_data, 6)

# visualize clustering
library(factoextra)
fviz_cluster(kmeans.result, data = numeric_data)


# print the clustering result
print(kmeans.result)
K-means clustering with 6 clusters of sizes 104, 91, 213, 233, 239, 120

Cluster means:
  type_school school_accreditation    gender  interest residence parent_age parent_salary
1   0.5288462            0.5288462 0.4134615 0.8365385 0.6442308   55.15385     0.4498611
2   0.7362637            0.6813187 0.4725275 2.3846154 1.0000000   58.60440     0.3728205
3   0.6666667            0.4741784 0.5258216 3.5399061 0.4835681   50.52113     0.5166093
4   0.6952790            0.5536481 0.4420601 3.2703863 0.8583691   54.01717     0.4693371
5   0.5271967            0.3849372 0.4937238 0.5020921 0.2677824   51.26778     0.5096885
6   0.4750000            0.3500000 0.5500000 1.6666667 0.1166667   46.15833     0.5410000
  house_area parent_was_in_college
1  0.5810192             0.4326923
2  0.5303736             0.0989011
3  0.5257512             0.5446009
4  0.5510987             0.2746781
5  0.5787364             0.7740586
6  0.4812833             0.8416667

Clustering vector:
   [1] 1 2 3 3 2 6 3 4 5 6 1 6 6 4 3 4 3 3 6 6 3 4 3 2 4 5 4 5 5 5 3 4 2 5 3 4 1 3 4 5 5 4 4 3 3
  [46] 5 5 4 1 5 6 1 5 3 5 4 1 6 6 4 5 3 5 3 4 4 5 3 5 4 4 5 6 2 1 4 1 4 5 3 4 5 2 5 4 4 1 5 3 4
  [91] 1 4 2 5 6 3 6 4 3 5 5 4 5 3 3 5 3 4 2 2 5 5 5 3 3 6 5 4 2 1 3 6 3 6 1 4 6 3 5 4 4 6 5 3 5
 [136] 5 4 3 4 4 4 2 6 6 5 3 5 1 6 3 6 6 2 5 1 3 1 5 1 4 1 3 4 4 5 5 1 2 3 3 1 5 2 3 4 3 3 5 3 5
 [181] 4 3 1 5 6 1 1 4 4 4 4 6 5 4 1 4 6 5 1 4 1 2 4 4 3 1 2 6 4 3 6 5 6 4 1 3 4 3 5 3 2 3 2 5 5
 [226] 5 5 6 4 5 1 5 5 5 5 2 1 5 3 2 1 3 5 5 4 4 6 5 5 1 2 3 5 4 5 6 3 4 6 4 2 4 6 3 4 5 2 5 4 5
 [271] 6 5 6 4 5 6 5 4 3 1 5 3 2 3 3 4 1 4 5 3 2 5 2 3 3 1 5 3 6 5 3 4 6 5 5 5 6 5 6 1 3 4 5 4 4
 [316] 4 3 1 1 6 2 2 4 6 5 4 6 4 6 4 4 3 5 2 4 1 6 5 5 5 5 5 3 3 5 6 5 4 3 4 3 5 5 6 1 6 3 2 5 6
 [361] 3 6 5 5 5 6 3 3 6 1 2 2 2 4 3 3 1 5 4 4 3 4 3 1 4 3 4 2 3 1 5 2 6 3 3 2 3 5 3 6 4 4 5 4 6
 [406] 4 4 5 4 3 3 4 5 2 3 1 5 3 5 4 3 6 4 1 2 2 6 1 1 4 6 3 6 2 4 6 4 6 4 3 5 5 2 2 4 6 5 6 5 4
 [451] 3 3 5 4 3 4 3 3 4 5 5 2 2 3 3 5 3 3 4 3 4 6 4 4 5 3 5 6 5 6 1 6 3 5 2 3 4 4 3 5 6 5 3 4 3
 [496] 4 6 2 6 4 4 4 4 5 1 4 4 6 2 4 6 3 5 2 1 4 1 3 6 1 5 2 1 3 5 5 4 5 6 6 6 4 3 3 2 4 3 3 6 3
 [541] 3 5 3 4 3 3 5 5 1 1 5 2 4 4 5 6 3 6 5 3 6 4 4 6 5 3 4 2 3 4 2 4 4 5 3 4 4 5 5 4 5 5 4 6 5
 [586] 4 3 5 5 4 6 1 1 4 5 6 1 4 3 4 4 1 3 4 1 3 4 5 4 3 3 5 5 6 2 1 3 5 2 5 3 5 1 6 1 2 3 3 2 4
 [631] 5 5 2 5 4 4 5 3 5 2 3 2 5 4 5 1 4 5 3 1 1 4 2 3 3 6 4 5 4 5 2 4 3 2 3 3 6 3 4 5 3 5 5 4 2
 [676] 3 1 2 1 4 5 4 6 4 1 2 3 3 3 4 5 3 6 3 5 3 5 5 5 3 4 3 5 6 5 5 3 4 5 4 3 3 2 6 3 4 1 2 5 3
 [721] 3 2 4 3 1 2 6 6 4 3 1 3 4 3 6 6 3 4 3 5 6 5 6 5 4 3 1 4 6 5 5 5 5 1 3 5 3 3 4 5 1 1 3 4 4
 [766] 5 2 2 5 4 4 4 5 5 3 3 5 6 2 5 5 4 5 5 4 1 4 5 3 5 5 1 1 1 5 3 6 4 4 3 3 5 4 5 4 4 5 4 1 5
 [811] 6 2 6 3 6 3 6 5 5 4 4 4 4 5 2 3 5 1 3 2 3 5 1 4 6 5 5 1 5 6 4 5 1 1 1 3 3 1 4 5 3 4 6 4 2
 [856] 4 6 4 3 3 4 4 4 2 5 4 2 5 3 1 4 3 6 4 4 3 4 1 3 4 5 2 1 3 2 1 5 4 4 6 6 4 5 4 6 1 4 3 5 5
 [901] 3 5 4 2 4 6 3 5 2 5 4 1 3 5 2 5 5 5 4 3 3 1 4 5 5 5 4 4 4 1 6 3 1 4 6 5 4 2 3 1 1 1 4 3 5
 [946] 3 1 4 4 4 2 3 3 3 5 5 1 1 5 1 5 3 6 4 2 3 5 5 5 5 4 2 5 4 4 6 4 3 2 5 5 3 3 6 2 4 2 6 4 3
 [991] 4 3 4 4 5 3 5 3 5 3

Within cluster sum of squares by cluster:
[1] 285.6366 426.7825 722.6048 655.5483 782.3111 828.9997
 (between_SS / total_SS =  76.9 %)

Available components:

[1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss" "betweenss"   
[7] "size"         "iter"         "ifault"      

The Silhouette coefficient

#average for each cluster 
avg_sil <- silhouette(kmeans.result$cluster, dist(numeric_data)) 

#k-means clustering with estimating k and initializations 
fviz_silhouette(avg_sil)
NA

The total within-cluster sum of squares

# Calculate total within-cluster sum of squares
total_withinss <- kmeans.result$tot.withinss
cat("Total Within-Cluster Sum of Squares:", sum(total_withinss), "\n")
Total Within-Cluster Sum of Squares: 3701.883 
true_labels <- c(1, 1, 2, 1, 2, 2, 3, 3, 4, 4)  # Adjust based on your actual true labels

cluster_assignments <- kmeans.result$cluster
 

BCubed recall and precision


# Calculate BCubed precision
precision <- 0
for (i in unique(true_labels)) {
  cluster_indices <- which(true_labels == i)
  precision <- precision + sum((table(cluster_assignments[cluster_indices]) * (table(cluster_assignments[cluster_indices]) - 1)) / sum(table(cluster_assignments[cluster_indices])))
}
precision <- precision / sum(table(cluster_assignments))

# Calculate BCubed recall
recall <- 0
for (j in unique(cluster_assignments)) {
  cluster_indices <- which(cluster_assignments == j)
  recall <- recall + sum((table(true_labels[cluster_indices]) * (table(true_labels[cluster_indices]) - 1)) / sum(table(true_labels[cluster_indices])))
}
recall <- recall / sum(table(true_labels))

cat("BCubed Precision:", precision, "\n")
BCubed Precision: 0 
cat("BCubed Recall:", recall, "\n")
BCubed Recall: 0 

The optimal number of clusters

To find the optimal number of clusters to use in the k-means algorithm, we’ll use the fviz_nbclust() function from the factoextrapackage to create a plot of the number of clusters vs. the total within sum of squares

# Function to calculate total within-cluster sum of squares (wss)
wss <- function(k) {
  kmeans_result <- kmeans(numeric_data, centers = k, nstart = 10)  # You can adjust nstart based on your preference
  return(sum(kmeans_result$tot.withinss))
}

# Calculate the total within-cluster sum of squares for different values of k
k_values <- 1:10  # You can adjust the range of k values
wss_values <- sapply(k_values, wss)

# Plot the elbow curve
plot(k_values, wss_values, type = "b", pch = 19, frame = FALSE, 
     xlab = "Number of Clusters (k)", ylab = "Total Within-Cluster Sum of Squares (WSS)",
     main = "Elbow Method")

# Adding a line to indicate the "elbow"
abline(v = which(diff(wss_values) == max(diff(wss_values))) + 1, col = "red")

NA
NA

According to the output the best number of clusters is one,

LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpJbXBvcnRhbnQgcGFja2FnZXM6DQoNCmBgYHtyfQ0Kc2V0d2QoIkRhdGFzZXQiKQ0KRGF0YXNldCA8LSByZWFkLmNzdigiZGF0YS5jc3YiKQ0KUHJlcHJvY2Vzc2VkX2RhdGFzZXQgPC0gIHJlYWQuY3N2KCJwcmVwcm9jZXNzZWRfZGF0YXNldC5jc3YiKSANCmlmKCFyZXF1aXJlKGdncGxvdDIpKXsNCmluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKX0NCmxpYnJhcnkoZ2dwbG90MikNCmlmKCFyZXF1aXJlKGRwbHlyKSl7DQppbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpfQ0KbGlicmFyeShkcGx5cikgDQppZighcmVxdWlyZShkcGx5cikpew0KaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKX0NCmxpYnJhcnkoZHBseXIpDQppZighcmVxdWlyZShsdG0pKXsNCmluc3RhbGwucGFja2FnZXMoImx0bSIpfQ0KbGlicmFyeShsdG0pDQppZiAoIXJlcXVpcmUoY2x1c3RlciwgcXVpZXRseSA9IFRSVUUpKSB7DQogIGluc3RhbGwucGFja2FnZXMoImNsdXN0ZXIiKQ0KfQ0KaWYgKCFyZXF1aXJlKGZhY3RvZXh0cmEsIHF1aWV0bHkgPSBUUlVFKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJmYWN0b2V4dHJhIikNCn0NCiANCmlmICghcmVxdWlyZShjYXJldCwgcXVpZXRseSA9IFRSVUUpKSB7DQogIGluc3RhbGwucGFja2FnZXMoImNhcmV0IikNCn0NCg0KaWYgKCFyZXF1aXJlKHBhcnR5a2l0LCBxdWlldGx5ID0gVFJVRSkpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygicGFydHlraXQiKQ0KfQ0KDQppZiAoIXJlcXVpcmUocnBhcnQsIHF1aWV0bHkgPSBUUlVFKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJycGFydCIpDQp9DQppZiAoIXJlcXVpcmUocnBhcnQucGxvdCwgcXVpZXRseSA9IFRSVUUpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInJwYXJ0LnBsb3QiKQ0KfQ0KaWYgKCFyZXF1aXJlKHRpZHl2ZXJzZSwgcXVpZXRseSA9IFRSVUUpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpDQp9DQogDQpgYGANCg0KIyBJVDMyNiBQcm9qZWN0IHtzdHlsZT0iY29sb3I6IGdyYXkifQ0KDQpcX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF9cX1xfXF8NCg0KIyMgVGhlIEdvYWwNCg0KT3VyIHByaW1hcnkgb2JqZWN0aXZlIG9mIHRoaXMgYW5hbHlzaXMgaXMgdG8gY2xhc3NpZnkgd2hhdGV2ZXIgYSBzdHVkZW50IHdpbGwgZ28gdG8gY29sbGVnZSBvciBub3QgdXNpbmcgdGhlIGNsYXNzaWZpY2F0aW9uIG1ldGhvZHMgYW5kIHRvIGlkZW50aWZ5IHRoZSBtYWluIGZhY3RvcnMgYW5kIHJlYXNvbnMgd2h5IHN0dWRlbnRzIGFyZSBsZXNzIGxpa2VseSB0byBwdXJzdWUgaGlnaGVyIGVkdWNhdGlvbiBpbmRpY2F0ZWQgYnkgIndpbGxfZ29fdG9fY29sbGVnZSIgYmVpbmcgJ0ZhbHNlJy4gQnkgbGV2ZXJhZ2luZyB0aGUgcHJvdmlkZWQgZGF0YXNldCB3aXRoIGF0dHJpYnV0ZXMgc3VjaCBhcyBzY2hvb2wgdHlwZSwgc2Nob29sIGFjY3JlZGl0YXRpb24sIGdlbmRlciwgaW50ZXJlc3QgaW4gY29sbGVnZSwgcmVzaWRlbmNlLCB3ZSBhaW0gdG8gZGlzY292ZXIgdGhlIG1vc3QgaW5mbHVlbnRpYWwgdmFyaWFibGVzIGFuZCB0aGVpciByZWxhdGlvbnNoaXBzIHdpdGggdGhlIGRlY2lzaW9uIG5vdCB0byBhdHRlbmQgY29sbGVnZS4NCg0KIyMgVGhlIFNvdXJjZQ0KDQpLYWdnbGUuY29tDQoNCiMjIFVSTCA6DQoNCjxodHRwczovL3d3dy5rYWdnbGUuY29tL2RhdGFzZXRzL3NhZGRhbWF6eWF6eS9nby10by1jb2xsZWdlLWRhdGFzZXQ+DQoNCiMjIEdlbmVyYWwgaW5mb3JtYXRpb24NCg0KLSAgIE51bWJlciBvZiBhdHRyaWJ1dGVzIDogMTENCi0gICBOdW1iZXIgb2Ygcm93cyAob2JqZWN0cykgOiAxMDAwDQotICAgVGhlIGNsYXNzIGxhYmVsOiBUaGUgY2xhc3MgbGFiZWwgaW4gb3VyIHByb2plY3QgaXMgdGhlIGF0dHJpYnV0ZSAid2lsbF9nb190b19jb2xsZWdlIi4gVGhpcyBhdHRyaWJ1dGUgaXMgYmluYXJ5LCBtZWFuaW5nIHRoYXQgaXQgY2FuIHRha2Ugb24gdHdvIHZhbHVlczogVHJ1ZSBmb3IgeWVzIG9yIEZhbHNlIGZvciBuby4gVGhlIHZhbHVlIG9mIHRoaXMgYXR0cmlidXRlIHdpbGwgYmUgdGhlIHRhcmdldCB2YXJpYWJsZSB0aGF0IHdlIGFyZSB0cnlpbmcgdG8gcHJlZGljdCBkdXJpbmcgb3VyIHByb2plY3QuDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQorLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsNCnwgQXR0cmlidXRlICAgICAgICAgICAgIHwgRGVzY3JpcHRpb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IFR5cGUgICAgICB8IFBvc3NpYmxlIHZhbHVlcyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rDQp8IHR5cGVfc2Nob29sICAgICAgICAgICB8IFRoZSB0eXBlIG9mIHNjaG9vbCB0aGUgc3R1ZGVudCBhdHRlbmRzICAgICAgICAgICAgICAgICAgICAgfCBCaW5hcnkgICAgfCBBY2FkZW1pYyAvIFZvY2F0aW9uYWwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCistLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKw0KfCBzY2hvb2xfYWNjcmVkaXRhdGlvbiAgfCBUaGUgcXVhbGl0eSBpZiBzY2hvb2wgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgQmluYXJ5ICAgIHwgQSAvIEIgKEEgaXMgYmV0dGVyIHRoYW4gQikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQorLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsNCnwgZ2VuZGVyICAgICAgICAgICAgICAgIHwgVGhlIHN0dWRlbnQncyBnZW5kZXIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IEJpbmFyeSAgICB8IE1hbGUgLyBGZW1hbGUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rDQp8IGludGVyZXN0ICAgICAgICAgICAgICB8IFRoZSBzdHVkZW50J3MgaW50ZXJlc3QgaW4gZ29pbmcgdG8gY29sbGVnZSAgICAgICAgICAgICAgICAgfCBOb21pbmFsICAgfCBWZXJ5IGludGVyZXN0ZWQgL0ludGVyZXN0ZWQgLyBMZXNzIEludGVyZXN0ZWQgLyBOb3QgSW50ZXJlc3RlZCAvVW5jZXJ0YWluIHwNCistLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKw0KfCByZXNpZGVuY2UgICAgICAgICAgICAgfCBUaGUgc3R1ZGVudCdzIHJlc2lkZW5jZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgQmluYXJ5ICAgIHwgVXJiYW4gLyBSdXJhbCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQorLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsNCnwgcGFyZW50X2FnZSAgICAgICAgICAgIHwgVGhlIGFnZSBvZiB0aGUgc3R1ZGVudCdzIHBhcmVudHMgICAgICAgICAgICAgICAgICAgICAgICAgICB8IE51bWVyaWMgICB8IDQwIC0gNjUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rDQp8IHBhcmVudF9zYWxhcnkgICAgICAgICB8IFRoZSBtb250aGx5IHNhbGFyeSBvZiB0aGUgc3R1ZGVudCdzIHBhcmVudHMgaW4gSURSL1J1cGlhaC4gfCBOdW1lcmljICAgfCAxMDAwSyAtIDEwTSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCnwgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgICAgICAgICB8ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KfCAgICAgICAgICAgICAgICAgICAgICAgfCBbMVJ1cGlhaCA9IDAuMDAwMjRTQVJdICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQorLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsNCnwgaG91c2VfYXJlYSAgICAgICAgICAgIHwgVGhlIHNpemUgb2YgdGhlIHN0dWRlbnQncyBob3VzZSBpbiBtZXRlciBzcXVhcmUgICAgICAgICAgICB8IE51bWVyaWMgICB8IDIwIC0gMTIwICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rDQp8IGF2ZXJhZ2VfZ3JhZGVzICAgICAgICB8IFRoZSBzdHVkZW50J3MgYXZlcmFnZSBncmFkZXMgaW4gc2Nob29sLiAgICAgICAgICAgICAgICAgICAgfCBOdW1lcmljICAgfCA3NSAtIDk4ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCistLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKw0KfCBwYXJlbnRfd2FzX2luX2NvbGxlZ2UgfCBXaGV0aGVyIHRoZSBzdHVkZW50J3MgcGFyZW50cyBhdHRlbmRlZCBjb2xsZWdlLiAgICAgICAgICAgIHwgQmluYXJ5ICAgIHwgVHJ1ZSAtIEZhbHNlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQorLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsNCnwgd2lsbF9nb190b19jb2xsZWdlICAgIHwgV2hldGhlciB0aGUgc3R1ZGVudCBwbGFucyB0byBnbyB0byBjb2xsZWdlLiAgICAgICAgICAgICAgICB8IEJpbmFyeSAgICB8IFRydWUgLSBGYWxzZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rDQoNCiMjIFNhbXBsZSBvZiBvdXIgZGF0YQ0KDQpgYGB7cn0NCmhlYWQoRGF0YXNldCkNCmBgYA0KDQpIZXJlIGFyZSBhIHNhbXBsZSBvZiA2IHJvdyBmcm9tIG91ciBkYXRhc2V0Lg0KDQojIyBNaXNzaW5nIHZhbHVlcw0KDQpgYGB7cn0NCnN1bShpcy5uYShEYXRhc2V0KSkNCmBgYA0KDQpUaGVyZSBhcmUgbm8gbWlzc2luZyB2YWx1ZXMgaW4gb3VyIGRhdGFzZXQuDQoNCiMjIFN0YXRpc3RpY2FsIGdyYXBocw0KDQpHcmFwaCAxOg0KDQpgYGB7cn0NCmRmID1kYXRhLmZyYW1lKERhdGFzZXQpDQpnZ3Bsb3QoZGF0YT1kZiwgYWVzKHggPSBpbnRlcmVzdCwgZmlsbCA9IHdpbGxfZ29fdG9fY29sbGVnZSkpICsNCiAgZ2VvbV9iYXIoKSArDQogIHNjYWxlX3hfZGlzY3JldGUobGltaXRzID0gYygnTm90IEludGVyZXN0ZWQnLCAnTGVzcyBJbnRlcmVzdGVkJywgJ1VuY2VydGFpbicsICdJbnRlcmVzdGVkJywgJ1ZlcnkgSW50ZXJlc3RlZCcpKSArDQogIGxhYnModGl0bGUgPSAnQ29sbGVnZSBpbnRlcmVzdCB2cyBDb2xsZWdlIGF0dGVuZGFuY2UgJykgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJUcnVlIiA9ICJhbnRpcXVld2hpdGUyIiwgIkZhbHNlIiA9ICJhbnRpcXVld2hpdGUzIikpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCg0KYGBgDQoNCkFjY29yZGluZyB0byB0aGUgZ3JhcGgsIHdoZXRoZXIgc3R1ZGVudHMgYXJlIGludGVyZXN0ZWQgaW4gZ29pbmcgdG8gY29sbGVnZSBvciBub3QgZG9lcyBub3QgYWZmZWN0IHdoZXRoZXIgdGhleSBhY3R1YWxseSBlbmQgdXAgYXR0ZW5kaW5nIENvbGxhZ2UgLiBUaGVyZSBpcyBhIGdyb3VwIG9mIGluZGl2aWR1YWxzIHdobyB3ZXJlIGludGVyZXN0ZWQgaW4gYXR0ZW5kaW5nIGJ1dCBkaWQgbm90IHJlY2VpdmUgYWNjZXB0YW5jZSwgd2hpbGUgb3RoZXJzIHdobyB3ZXJlIG5vdCBpbnRlcmVzdGVkIHdlcmUgYWNjZXB0ZWQuDQoNCkdyYXBoIDI6DQoNCmBgYHtyfQ0KDQpmaWx0ZXJlZF9UcnVlID1maWx0ZXIoRGF0YXNldCwgd2lsbF9nb190b19jb2xsZWdlID09ICdUcnVlJykNCmZpbHRlcmVkX0ZhbHNlID1zdWJzZXQoRGF0YXNldCwgd2lsbF9nb190b19jb2xsZWdlID09J0ZhbHNlJykNCg0KZ2dwbG90KCkgKw0KICBnZW9tX2RlbnNpdHkoZGF0YSA9IGZpbHRlcmVkX1RydWUsIGFlcyh4ID0gYXZlcmFnZV9ncmFkZXMsIGZpbGwgPSAiR29pbmcgdG8gQ29sbGVnZSIpLCBhbHBoYSA9IDAuNSkgKw0KICBnZW9tX2RlbnNpdHkoZGF0YSA9IGZpbHRlcmVkX0ZhbHNlLCBhZXMoeCA9IGF2ZXJhZ2VfZ3JhZGVzLCBmaWxsID0gIk5PVCBHb2luZyB0byBDb2xsZWdlIiksIGFscGhhID0gMC41KSArDQogIGxhYnMoeCA9ICJBdmVyYWdlIEdyYWRlcyIsIHkgPSAiRGVuc2l0eSIpICsNCiAgZ2d0aXRsZSgiQ29tcGFyaXNvbiBvZiBBdmVyYWdlIEdyYWRlcyBmb3IgU3R1ZGVudHMgR29pbmcgdG8gQ29sbGVnZSBhbmQgTk9UIEdvaW5nIHRvIENvbGxlZ2UiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIkdvaW5nIHRvIENvbGxlZ2UiID0gImFudGlxdWV3aGl0ZTQiLCAiTk9UIEdvaW5nIHRvIENvbGxlZ2UiID0gImFudGlxdWV3aGl0ZTEiKSkNCg0KYGBgDQoNClRoZSBncmFwaCBzaG93cyB0aGF0IHRoZSBhdmVyYWdlIGdyYWRlcyBmb3Igc3R1ZGVudHMgd2hvIGhhZCBhY2NlcHRlZCB0byBnbyB0byBjb2xsZWdlIHdlcmUgaGlnaGVyIHRoYW4gdGhvc2Ugd2hvIGRpZCBub3QgZW50ZXIgY29sbGVnZSAsIGFuZCB0aGlzIGluZGljYXRlcyB0aGUgZXhpc3RlbmNlIG9mIGEgY29ycmVsYXRpb24gYmV0d2VlbiB0aG9zZSB3aG8gZ29pbmcgdG8gY29sbGVnZSBhbmQgdGhlIGF2ZXJhZ2UgZ3JhZGVzDQoNCkdyYXBoIDM6DQoNCmBgYHtyfQ0KRGF0YXNldF9wZXJjZW50YWdlIDwtIERhdGFzZXQgJT4lDQogIGdyb3VwX2J5KHR5cGVfc2Nob29sKSAlPiUNCiAgc3VtbWFyaXNlKHBlcmNlbnRhZ2UgPSBtZWFuKHdpbGxfZ29fdG9fY29sbGVnZSA9PSAiVHJ1ZSIpICogMTAwKQ0KDQojIENyZWF0ZSBhIHBlcmNlbnRhZ2UgY2hhcnQNCmdncGxvdChEYXRhc2V0X3BlcmNlbnRhZ2UsIGFlcyh4ID0gdHlwZV9zY2hvb2wsIHkgPSBwZXJjZW50YWdlLCBmaWxsID0gdHlwZV9zY2hvb2wpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArDQogIGxhYnModGl0bGUgPSAiUGVyY2VudGFnZSBvZiBTdHVkZW50cyBHb2luZyB0byBDb2xsZWdlIGJ5IFR5cGUgb2YgU2Nob29sIiwNCiAgICAgICB4ID0gIlR5cGUgb2YgU2Nob29sIiwNCiAgICAgICB5ID0gIlBlcmNlbnRhZ2UiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIkFjYWRlbWljIiA9ICJhbnRpcXVld2hpdGUzIiwgIlZvY2F0aW9uYWwiID0gImFudGlxdWV3aGl0ZTIiKSkgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KIA0KYGBgDQoNClRoaXMgZ3JhcGggc2hvd3MgdGhlIGltcGFjdCBvZiB0aGUgdHlwZSBvZiBoaWdoIHNjaG9vbCBhdHRlbmRlZCBieSBzdHVkZW50cyBvbiB0aGVpciBjb2xsZWdlIGF0dGVuZGFuY2UgLiBCYXNlZCBvbiB0aGUgYmFyIGNoYXJ0Og0KDQotICAgYW1vbmcgc3R1ZGVudHMgZnJvbSBBY2FkZW1pYyBoaWdoIHNjaG9vbHMsIDMxMyBhcmUgZ29pbmcgdG8gY29sbGVnZSwgYW5kIDI5NiBhcmUgbm90Lg0KDQotICAgYW1vbmcgc3R1ZGVudHMgZnJvbSBWb2NhdGlvbmFsIGhpZ2ggc2Nob29scywgMTg3IGFyZSBnb2luZyB0byBjb2xsZWdlLCBhbmQgMjA0IGFyZSBub3QNCg0KVGhlc2UgaW5mb3JtYXRpb24gdGVsbCB1cyB0aGF0IGEgaGlnaGVyIHByb3BvcnRpb24gb2Ygc3R1ZGVudHMgZnJvbSBhY2FkZW1pYyBoaWdoIHNjaG9vbHMgYXJlIGdvaW5nIHRvIGNvbGxlZ2UgY29tcGFyZWQgdG8gdGhvc2UgZnJvbSB2b2NhdGlvbmFsIHNjaG9vbHMgd2hpY2ggc3VnZ2VzdCB0aGF0IHRoZSB0eXBlIG9mIHNjaG9vbCBhdHRlbmRlZC4NCg0KR3JhcGggNDoNCg0KYGBge3J9DQpnZ3Bsb3QoRGF0YXNldCwgYWVzKHggPSBhdmVyYWdlX2dyYWRlcykpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSA1LCBmaWxsID0gImFudGlxdWV3aGl0ZTIiLCBjb2xvciA9ICJhbnRpcXVld2hpdGU0IikgKw0KICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBzdHVkZW50cycgZ3JhZGVzIiwNCiAgICAgICB4ID0gIlN0dWRlbnRzJyBhdmVyYWdlIGdyYWRlcyIsDQogICAgICAgeSA9ICJGcmVxdWVuY3kiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNClRoaXMgaGlzdG9ncmFtIHNob3cgdXMgdGhhdCB0aGUgbWFqb3JpdHkgb2YgdGhlIHN0dWRlbnRzIGluIHRoZSBkYXRhc2V0IGFyZSBwZXJmb3JtaW5nIHdlbGwgc2luY2UgaXQgc2VlbXMgbGlrZSB0aGVpciBncmFkZXMgYXJlIHNwYW5uaW5nIGJldHdlZW4gNzUgYW5kIDk4LiBUaGlzIGFuYWx5c2lzIHdpbGwgaGVscCB1cyBkZXRlcm1pbmUgd2hldGhlciB0aGUgYWNhZGVtaWMgcGVyZm9ybWFuY2UgbGV2ZWwgb2Ygc3R1ZGVudHMgaXMgYSBjb250cmlidXRpbmcgZmFjdG9yIHRvIHRoZWlyIGNvbGxlZ2UgYXR0ZW5kYW5jZSBvciBub3QuDQoNCiMjIFN0YXRpc3RpY2FsIE1lYXN1cmVzDQoNCjEuICBUaGUgc3R1ZGVudCdzIGFjYWRlbWljIHBlcmZvcm1hbmNlIGFuYWx5c2lzOg0KDQpgYGB7cn0NCnN1bW1hcnkoRGF0YXNldCRhdmVyYWdlX2dyYWRlcykNCg0KYGBgDQoNClRoZSBzdHVkZW50IGdyYWRlcyBpbiBvdXIgZGF0YXNldCByYW5nZSBmcm9tIDc1LjAwIHRvIDk4LjAwLCB3aXRoIGEgbWVkaWFuIG9mIDg1LjU4IGFuZCBhbiBhdmVyYWdlIG9mIDg2LjEwLiBUaGlzIHN1Z2dlc3RzIHRoYXQgbW9zdCBzdHVkZW50cyBhcmUgZG9pbmcgd2VsbCBhcyBub25lIG9mIHRoZW0gaGF2ZSBhdmVyYWdlIGdyYWRlcyBiZWxvdyA1MC4gSG93ZXZlciwgaXQncyBpbnRlcmVzdGluZyB0byBub3RlIHRoYXQgc29tZSBzdHVkZW50cyBoYXZlIG11Y2ggaGlnaGVyIG9yIGxvd2VyIGdyYWRlcyB0aGFuIHRoZSBhdmVyYWdlLCBtYWlubHkgZHVlIHRvIHRoZSB3aWRlIHJhbmdlIG9mIGdyYWRlcy4uDQoNCjIuICBUaGUgc29jaW9lY29ub21pYyBzdGF0dXMgb2Ygc3R1ZGVudHMnIGZhbWlsaWVzIGFuYWx5c2lzOg0KDQpgYGB7cn0NCnN1bW1hcnkoRGF0YXNldCRwYXJlbnRfc2FsYXJ5KQ0KYGBgDQoNCkluIHRoZSBkYXRhc2V0LCB3ZSd2ZSBnb3Qgc3R1ZGVudHMgcGFyZW50cyB3aXRoIHNhbGFyaWVzIHJhbmdpbmcgZnJvbSAxLDAwMCwwMDAgdG8gMTAsMDAwLDAwMCBJRFIvUnVwaWFoLiBUaGUgbWVkaWFuIHNhbGFyeSBpcyA1LDQ0MCwwMDAgSURSL1J1cGlhaCwgYW5kIHRoZSBhdmVyYWdlIGlzIDUsMzgxLDU3MCBJRFIvUnVwaWFoLiBUaGlzIGRhdGEgdGVsbHMgdXMgdGhhdCBtYW55IHBhcmVudHMgaW4gb3VyIGRhdGFzZXQgZWFybiBsZXNzIHRoYW4gdGhlIGF2ZXJhZ2Ugc2FsYXJ5IGluIEluZG9uZXNpYSwgd2hpY2ggaXMgMTQ2LDAwMCwwMDAgSURSLiBUaGlzIHN1Z2dlc3RzIHRoYXQgcXVpdGUgYSBmZXcgc3R1ZGVudHMgaW4gb3VyIGRhdGFzZXQgY29tZSBmcm9tIGZhbWlsaWVzIHdpdGggbGltaXRlZCBmaW5hbmNlcy4gQW5kIHRoaXMgZmluYW5jaWFsIHNpdHVhdGlvbiBjb3VsZCBjZXJ0YWlubHkgaW1wYWN0IHRoZWlyIGFiaWxpdHkgdG8gZ2V0IHRocm91Z2ggY29sbGVnZS4NCg0KYGBge3J9DQpzdW1tYXJ5KERhdGFzZXQkaG91c2VfYXJlYSkNCmBgYA0KDQpBZGRpdGlvbmFsbHkgd2UgY2FuIHV0aWxpemUgdGhlIGhvdXNlIGFyZWEgYXR0cmlidXRlIHRvIGdhaW4gYSBkZWVwZXIgdW5kZXJzdGFuZGluZyBvZiB0aGUgc29jaW9lY29ub21pYyBzdGF0dXMgb2Ygc3R1ZGVudHMnIGZhbWlsaWVzLCB3aGVyZSBzdHVkZW50cyB3aXRoIGhvdXNlcyBzaWduaWZpY2FudGx5IGxhcmdlciB0aGFuIHRoZSBtZWFuIG1pZ2h0IGluZGljYXRlIGEgaGlnaGVyIHNvY2lvZWNvbm9taWMgc3RhdHVzLCB3aGlsZSB0aG9zZSB3aXRoIGhvdXNlcyBjb25zaWRlcmFibHkgc21hbGxlciB0aGFuIHRoZSBtZWFuIG1pZ2h0IHJlZmxlY3QgYSBjb21wYXJhdGl2ZWx5IGxvd2VyIHNvY2lvZWNvbm9taWMgc3RhdHVzLiBCYXNlZCBvbiB0aGUgc2hvd24gb3V0cHV0LCB0aGUgaG91c2UgYXJlYXMgcmFuZ2UgZnJvbSBbMjAuMDAtMTIwLjAwIOOOoV0uIFRoZSBtZWRpYW4gaG91c2UgYXJlYSBpcyA3NS41MCDjjqEgaW5kaWNhdGVzIHRoYXQgZmFtaWxpZXMgd2l0aCBob3VzZSBhcmVhcyBhcm91bmQgdGhpcyB2YWx1ZSBsaWtlbHkgaGF2ZSBtb2RlcmF0ZSBzb2Npb2Vjb25vbWljIHN0YXR1cyB3aXRoIGhvdXNlcyB0aGF0IG5laXRoZXIgdmVyeSBzbWFsbCBub3IgdmVyeSBsYXJnZS4NCg0KMy4gIFVuZGVyc3RhbmRpbmcgUGFyZW50IEFnZSBSYW5nZSBhbmQgVmFyaWF0aW9uIGluIGl0cyBWYWx1ZXMNCg0KYGBge3J9DQpzdW1tYXJ5KERhdGFzZXQkcGFyZW50X2FnZSkNClNEPXNkKERhdGFzZXQkcGFyZW50X2FnZSkNCk1lYW5BZ2U9bWVhbihEYXRhc2V0JHBhcmVudF9hZ2UpDQpjYXQoImNvZWZmaWNpZW50IG9mIHZhcmlhdGlvbjoiLFNEL01lYW5BZ2UqMTAwLCIlIikNCg0KYGBgDQoNClRoaXMgc3VtbWFyeSBwcm92aWRlcyB0aGUgcmFuZ2UgZm9yIGFnZSBhdHRyaWJ1dGUgWzQwLDY1XSB3aGljaCBpbmRpY2F0ZXMgdGhhdCBhbGwgcGFyZW50IGluIG1pZGRsZSBhZ2UgZHVyaW5nIHRoaXMgYWdlIHBhcmVudCBoYXZlIG1vcmUgY29uY2VybiBhYm91dCB0aGVpciBjaGlsZHJlbiAsIHRoZSBjb2VmZmljaWVudCBvZiB2YXJpYXRpb249IDYuNyUgd2hpY2ggaW5kaWNhdGVzIGxvd2VyIHZhcmlhdGlvbiAsYW5kIHRoZSB2YWx1ZSBvZiBhdHRyaWJ1dGUgcGFyZW50X2FnZXJhcmUgYXJlIHJlbGF0aXZlbHkgY2xvc2UgdG8gdGhlIG1lYW4gb3ZlcmFsbCAyNSUgb2YgdGhlbSBoYXZlIGFuIGFnZSBiZWxvdyBvciBlcXVhbCB0byA1MCAsIDc1JSBoYXZlIGFuIGFnZSBiZWxvdyBvciBlcXVhbCB0byA1NCBhbmQgdGhlIG1lZGlhbiB2YWx1ZSBpcyA1Mg0KDQojIyBPdXRsaWVycyBhbmFseXNpcw0KDQpgYGB7cn0NCiMjI3BhcmVudCBhZ2Ugb3V0bGllcnMNCnF1YXJ0aWxlcyA8LSBxdWFudGlsZShEYXRhc2V0JHBhcmVudF9hZ2UsIHByb2JzPWMoLjI1LCAuNzUpLCBuYS5ybSA9IEZBTFNFKQ0KSVFSIDwtIElRUihEYXRhc2V0JHBhcmVudF9hZ2UpDQoNCkxvd2VyIDwtIHF1YXJ0aWxlc1sxXSAtIDEuNSpJUVINClVwcGVyIDwtIHF1YXJ0aWxlc1syXSArIDEuNSpJUVIgDQoNCmRhdGFfbm9fb3V0bGllciA8LSBzdWJzZXQoRGF0YXNldCwgRGF0YXNldCRwYXJlbnRfYWdlID4gTG93ZXIgJiBEYXRhc2V0JHBhcmVudF9hZ2UgPCBVcHBlcikNCmRpbShkYXRhX25vX291dGxpZXIpDQoNCiMjI3BhcmVudCBzYWxhcnkgb3V0bGllcnMNCnF1YXJ0aWxlcyA8LSBxdWFudGlsZShEYXRhc2V0JHBhcmVudF9zYWxhcnksIHByb2JzPWMoLjI1LCAuNzUpLCBuYS5ybSA9IEZBTFNFKQ0KSVFSIDwtIElRUihEYXRhc2V0JHBhcmVudF9zYWxhcnkpDQoNCkxvd2VyIDwtIHF1YXJ0aWxlc1sxXSAtIDEuNSpJUVINClVwcGVyIDwtIHF1YXJ0aWxlc1syXSArIDEuNSpJUVIgDQoNCmRhdGFfbm9fb3V0bGllciA8LSBzdWJzZXQoZGF0YV9ub19vdXRsaWVyLCBkYXRhX25vX291dGxpZXIkcGFyZW50X3NhbGFyeT4gTG93ZXIgJiBkYXRhX25vX291dGxpZXIkcGFyZW50X3NhbGFyeSA8IFVwcGVyKQ0KZGltKGRhdGFfbm9fb3V0bGllcikNCg0KDQojIyNhdmVyZ2UgZ3JhZGVzIG91dGxpZXJzDQpxdWFydGlsZXMgPC0gcXVhbnRpbGUoRGF0YXNldCRhdmVyYWdlX2dyYWRlcywgcHJvYnM9YyguMjUsIC43NSksIG5hLnJtID0gRkFMU0UpDQpJUVIgPC0gSVFSKERhdGFzZXQkYXZlcmFnZV9ncmFkZXMpDQoNCkxvd2VyIDwtIHF1YXJ0aWxlc1sxXSAtIDEuNSpJUVINClVwcGVyIDwtIHF1YXJ0aWxlc1syXSArIDEuNSpJUVIgDQoNCmRhdGFfbm9fb3V0bGllciA8LSBzdWJzZXQoZGF0YV9ub19vdXRsaWVyLCBkYXRhX25vX291dGxpZXIkYXZlcmFnZV9ncmFkZXM+IExvd2VyICYgZGF0YV9ub19vdXRsaWVyJGF2ZXJhZ2VfZ3JhZGVzIDwgVXBwZXIpDQpkaW0oZGF0YV9ub19vdXRsaWVyKQ0KDQoNCiMjI2hvdXNlIGFyZWEgb3V0bGllcnMNCnF1YXJ0aWxlcyA8LSBxdWFudGlsZShEYXRhc2V0JGhvdXNlX2FyZWEsIHByb2JzPWMoLjI1LCAuNzUpLCBuYS5ybSA9IEZBTFNFKQ0KSVFSIDwtIElRUihEYXRhc2V0JGhvdXNlX2FyZWEpDQoNCkxvd2VyIDwtIHF1YXJ0aWxlc1sxXSAtIDEuNSpJUVINClVwcGVyIDwtIHF1YXJ0aWxlc1syXSArIDEuNSpJUVIgDQoNCmRhdGFfbm9fb3V0bGllciA8LSBzdWJzZXQoZGF0YV9ub19vdXRsaWVyLCBkYXRhX25vX291dGxpZXIkaG91c2VfYXJlYT4gTG93ZXIgJiBkYXRhX25vX291dGxpZXIkaG91c2VfYXJlYSA8IFVwcGVyKQ0KDQpGb3VuZGVkX091dGxpZXJzPWRhdGEuZnJhbWUoYW50aV9qb2luKERhdGFzZXQsZGF0YV9ub19vdXRsaWVyKSkNCnByaW50KEZvdW5kZWRfT3V0bGllcnMpDQpgYGANCg0KQWZ0ZXIgY29uZHVjdGluZyBkYXRhIGFuYWx5c2lzIGFuZCBpZGVudGlmeWluZyBvdXRsaWVycywgb3VyIGluc3BlY3Rpb24gcmV2ZWFscyB0aGF0IHRoZSBkZXRlY3RlZCBvdXRsaWVycyByZXByZXNlbnQgaW5oZXJlbnQgdmFyaWF0aW9uIHdpdGhpbiB0aGUgcG9wdWxhdGlvbi4gUmVnYXJkaW5nIFBhcmVudF9hZ2UsIG91dGxpZXJzIGFyZSBvYnNlcnZlZCBmb3IgdmFsdWVzIGJlbG93IDQ0IGFuZCBhYm92ZSA2NS4gSG93ZXZlciwgaXQgc2hvdWxkIGJlIG5vdGVkIHRoZSBhZ2UgZnJvbSA0MCB0byA2NSBmYWxsIHdpdGhpbiB0aGUgZXhwZWN0ZWQgbWVhbiBvZiBvdXIgZGF0YXNldCBtZWFuaW5nIHRoYXQgaXQgZG9lc24ndCBpbmRpY2F0ZSB0aGF0IHRoZXkgYXJlIG91dGxpZXJzIC4gRm9yIHBhcmVudF9zYWxhcnksIHdlIGZvdW5kIHR3byBvdXRsaWVyczogb25lIGJlbG93IDEsMzI2LDI1MCBpbmQg4omIIDg1IFVTRCBhbmQgYW5vdGhlciBhYm92ZSA5LDQxNiwyNTAgaW5kIOKJiCA2MDYgVVNELiBUaGUgbWluaW11bSBhbmQgbWF4aW11bSB2YWx1ZXMgd2VyZSBkZXRlcm1pbmVkIHRvIGJlIDEsMDAwLDAwMCBpbmQg4omIIDY0IFVTRCBhbmQgMTAsMDAwLDAwMCBpbmQg4omIIDY0NCBVU0QsIHJlc3BlY3RpdmVseS4gSW4gdGhlIGNhc2Ugb2YgZ3JhZGVzLCB0d2VsdmUgb3V0bGllcnMgd2VyZSBpZGVudGlmaWVkLCByYW5naW5nIGZyb20gYmVsb3cgNzYgdG8gYWJvdmUgOTcuIE5ldmVydGhlbGVzcywgc2luY2UgdGhlIGRhdGEgZmFsbHMgd2l0aGluIHRoZSBhY2NlcHRhYmxlIHJhbmdlIG9mIDAgdG8gMTAwLCB0aGVzZSBvdXRsaWVycyBzaG91bGQgYmUgcmV0YWluZWQgYXMgdGhleSBhcmUgc3RpbGwgY29uc2lkZXJlZCBub3JtYWwgYW5kIHdpdGhpbiB0aGUgdXN1YWwgZ3JhZGUgcmFuZ2UuIEZpbmFsbHksIGZvciBob3VzZV9hcmVhLCB3ZSBmb3VuZCBlbGV2ZW4gb3V0bGllcnMgYmVsb3cgMzQuNG0gYW5kIGFib3ZlIDExNW0sIHdpdGggdGhlIG1pbmltdW0gYmVpbmcgMjBtIGFuZCB0aGUgbWF4aW11bSBiZWluZyAxMjBtLiBIb3dldmVyLCB0aGVzZSB2YWx1ZXMgYXJlIHN0aWxsIGNvbnNpZGVyZWQgdHlwaWNhbCBmb3IgdGhlIHBvcHVsYXRpb24uDQoNCiMjIE5vcm1hbGl6YXRpb24NCg0KYGBge3J9DQpub3JtYWxpemUgPC0gZnVuY3Rpb24oeCkge3JldHVybigoeC1taW4oeCkpLyAobWF4KHgpLW1pbih4KSkpfQ0KZGF0YXNldFdpdGhvdXROb3JtYWxpemF0aW9uPC1EYXRhc2V0DQpEYXRhc2V0JHBhcmVudF9zYWxhcnk8LW5vcm1hbGl6ZShkYXRhc2V0V2l0aG91dE5vcm1hbGl6YXRpb24kcGFyZW50X3NhbGFyeSkNCkRhdGFzZXQkaG91c2VfYXJlYTwtbm9ybWFsaXplKGRhdGFzZXRXaXRob3V0Tm9ybWFsaXphdGlvbiRob3VzZV9hcmVhKQ0KcHJpbnQoRGF0YXNldCkNCmBgYA0KDQpXZSBhcHBsaWVkIG5vcm1hbGl6YXRpb24gdG8gdGhlICdwYXJlbnRfc2FsYXJ5JyBhbmQgJ2hvdXNlX2FyZWEnIGF0dHJpYnV0ZXMsIHNjYWxpbmcgdGhlaXIgdmFsdWVzIHRvIGEgcmFuZ2UgYmV0d2VlbiAwIGFuZCAxLiBUaGlzIG5vcm1hbGl6YXRpb24gcHJvY2VzcyBncmVhdGx5IGZhY2lsaXRhdGVzIGRhdGEgaGFuZGxpbmcgYW5kIGFuYWx5c2lzLCBlbnN1cmluZyB0aGF0IHRoZXNlIGF0dHJpYnV0ZXMgYXJlIG9uIGEgY29uc2lzdGVudCBzY2FsZS4gV2hpY2ggd2lsbCBpbXByb3ZlIHRoZSByZWxpYWJpbGl0eSBvZiBvdXIgZGF0YSBhbmFseXNpcyBhbmQgZW5hYmxlIGJldHRlciBjb25jbHVzaW9ucyB0byBiZSBkcmF3biBmcm9tIHRoZSBkYXRhc2V0LiBOb3JtYWxpemF0aW9uIGlzIGEgY3J1Y2lhbCBzdGVwIGluIHByZXBhcmluZyB0aGUgZGF0YSBmb3IgbW9kZWxpbmcsIGFzIGl0IHByZXZlbnRzIGF0dHJpYnV0ZXMgd2l0aCBsYXJnZXIgbnVtZXJpY2FsIHJhbmdlcyBmcm9tIGRvbWluYXRpbmcgdGhlIGFuYWx5c2lzIGFuZCBlbnN1cmVzIGZhaXIgdHJlYXRtZW50IGZvciBhbGwgZmVhdHVyZXMuDQoNCiMjIERpc2NyZXRpemF0aW9uDQoNCmBgYHtyfQ0KDQoNCkRhdGFzZXQkYXZlcmFnZV9ncmFkZXMgW0RhdGFzZXQkYXZlcmFnZV9ncmFkZXMgPj0gOTVdIDwtICcrQScNCkRhdGFzZXQkYXZlcmFnZV9ncmFkZXMgWzk1ID5EYXRhc2V0JGF2ZXJhZ2VfZ3JhZGVzICYgRGF0YXNldCRhdmVyYWdlX2dyYWRlcyA+PSA5MF0gPC0gJ0EnDQpEYXRhc2V0JGF2ZXJhZ2VfZ3JhZGVzIFs5MCA+RGF0YXNldCRhdmVyYWdlX2dyYWRlcyAmIERhdGFzZXQkYXZlcmFnZV9ncmFkZXMgPj0gODVdIDwtICcrQicNCkRhdGFzZXQkYXZlcmFnZV9ncmFkZXMgWzg1ID5EYXRhc2V0JGF2ZXJhZ2VfZ3JhZGVzICYgRGF0YXNldCRhdmVyYWdlX2dyYWRlcyA+PSA4MF0gPC0gJ0InDQpEYXRhc2V0JGF2ZXJhZ2VfZ3JhZGVzIFs4MCA+RGF0YXNldCRhdmVyYWdlX2dyYWRlcyAmIERhdGFzZXQkYXZlcmFnZV9ncmFkZXMgPj0gNzVdIDwtICcrQycNCkRhdGFzZXQkYXZlcmFnZV9ncmFkZXMgWzc1ID5EYXRhc2V0JGF2ZXJhZ2VfZ3JhZGVzICYgRGF0YXNldCRhdmVyYWdlX2dyYWRlcyA+PSA3MF0gPC0gJ0MnDQpEYXRhc2V0JGF2ZXJhZ2VfZ3JhZGVzIFs3MCA+RGF0YXNldCRhdmVyYWdlX2dyYWRlcyAmIERhdGFzZXQkYXZlcmFnZV9ncmFkZXMgPj0gNjVdIDwtICcrRCcNCkRhdGFzZXQkYXZlcmFnZV9ncmFkZXMgWzY1ID5EYXRhc2V0JGF2ZXJhZ2VfZ3JhZGVzICYgRGF0YXNldCRhdmVyYWdlX2dyYWRlcyA+PSA2MF0gPC0gJ0QnDQpEYXRhc2V0JGF2ZXJhZ2VfZ3JhZGVzIFs2MCA+RGF0YXNldCRhdmVyYWdlX2dyYWRlcyAmIERhdGFzZXQkYXZlcmFnZV9ncmFkZXMgPj0gMF0gPC0gJ0YnDQpEYXRhc2V0JGF2ZXJhZ2VfZ3JhZGVzIDwtIGFzLmNoYXJhY3RlcihEYXRhc2V0JGF2ZXJhZ2VfZ3JhZGVzICkNCnByaW50KERhdGFzZXQpDQpgYGANCg0KV2UgdHJhbnNmb3JtZWQgdGhlIHBhcmVudF9hZ2UgYXR0cmlidXRlIGludG8gaW50ZXJ2YWxzIGJ5IGRpdmlkaW5nIHRoZSB2YWx1ZXMgdG8gYmUgZmFsbCBvbiBvbmUgb2YgdHdvIHBvc3NpYmxlIGludGVydmFsIGxhYmVscyB3aXRoIGVxdWFsIHdpZHRoIHdoaWNoIGlzKDQwLDUwXSwoNTAsNjBdIGJ5IGRpc2NyZXRpemF0aW9uIHRoZSB2YWx1ZXMgd2VsbCBiZSBzaW1wbGVyIHRvIGNsYXNzaWZ5IG9yIHBlcmZvcm0gb3RoZXIgbWV0aG9kcyB0aGF0IGNhbiBoZWxwIHVzIGxhdGVyIGluIG91ciBtb2RlbC4NCg0KYW5kIHRvIGJldHRlciB1dGlsaXplIGFuZCBpbnRlcnByZXQgdGhlIGdyYWRlcyBhdHRyaWJ1dGVzIGZvciBlYWNoIHN0dWRlbnQsIHdlIGhhdmUgY29udmVydGVkIHRoZSBudW1lcmljIGdyYWRlcyBpbnRvIGxldHRlciBncmFkZXMgKEErLCBBLCBCKywgQiwgQyssIEMsIEQrLCBELCBGKS4gVGhpcyB0cmFuc2Zvcm1hdGlvbiB3YXMgdW5kZXJ0YWtlbiB0byBmb2N1cyBvbiB0aGUgZ2VuZXJhbCBsZXR0ZXIgZ3JhZGUgcmVwcmVzZW50YXRpb24gcmF0aGVyIHRoYW4gdGhlIHByZWNpc2UgbnVtZXJpY2FsIHZhbHVlcy4NCg0KIyMgRW5jb2RpbmcNCg0KYGBge3J9DQpEYXRhc2V0JHBhcmVudF93YXNfaW5fY29sbGVnZVtEYXRhc2V0JHBhcmVudF93YXNfaW5fY29sbGVnZT09IlRSVUUiXTwtMQ0KRGF0YXNldCRwYXJlbnRfd2FzX2luX2NvbGxlZ2VbRGF0YXNldCRwYXJlbnRfd2FzX2luX2NvbGxlZ2U9PSJUcnVlIl08LTENCkRhdGFzZXQkcGFyZW50X3dhc19pbl9jb2xsZWdlW0RhdGFzZXQkcGFyZW50X3dhc19pbl9jb2xsZWdlPT0iRkFMU0UiXTwtMA0KRGF0YXNldCRwYXJlbnRfd2FzX2luX2NvbGxlZ2VbRGF0YXNldCRwYXJlbnRfd2FzX2luX2NvbGxlZ2U9PSJGYWxzZSJdPC0wDQoNCkRhdGFzZXQkd2lsbF9nb190b19jb2xsZWdlW0RhdGFzZXQkd2lsbF9nb190b19jb2xsZWdlPT0iVFJVRSJdPC0wDQpEYXRhc2V0JHdpbGxfZ29fdG9fY29sbGVnZVtEYXRhc2V0JHdpbGxfZ29fdG9fY29sbGVnZT09IlRydWUiXTwtMA0KRGF0YXNldCR3aWxsX2dvX3RvX2NvbGxlZ2VbRGF0YXNldCR3aWxsX2dvX3RvX2NvbGxlZ2U9PSJGQUxTRSJdPC0xDQpEYXRhc2V0JHdpbGxfZ29fdG9fY29sbGVnZVtEYXRhc2V0JHdpbGxfZ29fdG9fY29sbGVnZT09IkZhbHNlIl08LTENCg0KRGF0YXNldCRnZW5kZXJbRGF0YXNldCRnZW5kZXI9PSJGZW1hbGUiXTwtMQ0KRGF0YXNldCRnZW5kZXJbRGF0YXNldCRnZW5kZXI9PSJNYWxlIl08LTANCg0KRGF0YXNldCRzY2hvb2xfYWNjcmVkaXRhdGlvbltEYXRhc2V0JHNjaG9vbF9hY2NyZWRpdGF0aW9uPT0iQSJdPC0xDQpEYXRhc2V0JHNjaG9vbF9hY2NyZWRpdGF0aW9uW0RhdGFzZXQkc2Nob29sX2FjY3JlZGl0YXRpb249PSJCIl08LTANCg0KRGF0YXNldCRpbnRlcmVzdFtEYXRhc2V0JGludGVyZXN0PT0iVmVyeSBJbnRlcmVzdGVkIl08LTQNCkRhdGFzZXQkaW50ZXJlc3RbRGF0YXNldCRpbnRlcmVzdD09IkludGVyZXN0ZWQiXTwtMw0KRGF0YXNldCRpbnRlcmVzdFtEYXRhc2V0JGludGVyZXN0PT0iTGVzcyBJbnRlcmVzdGVkIl08LTINCkRhdGFzZXQkaW50ZXJlc3RbRGF0YXNldCRpbnRlcmVzdD09Ik5vdCBJbnRlcmVzdGVkIl08LTENCkRhdGFzZXQkaW50ZXJlc3RbRGF0YXNldCRpbnRlcmVzdD09IlVuY2VydGFpbiJdPC0wDQoNCg0KRGF0YXNldCR0eXBlX3NjaG9vbFtEYXRhc2V0JHR5cGVfc2Nob29sPT0iQWNhZGVtaWMiXTwtMSANCkRhdGFzZXQkdHlwZV9zY2hvb2xbRGF0YXNldCR0eXBlX3NjaG9vbD09IlZvY2F0aW9uYWwiXTwtMA0KDQpEYXRhc2V0JHJlc2lkZW5jZVtEYXRhc2V0JHJlc2lkZW5jZT09IlVyYmFuIl08LTENCkRhdGFzZXQkcmVzaWRlbmNlW0RhdGFzZXQkcmVzaWRlbmNlPT0iUnVyYWwiXTwtMA0KcHJpbnQoRGF0YXNldCkNCmBgYA0KDQpTaW5jZSBlbmNvZGluZyBpcyBhbiBpbXBvcnRhbnQgc3RlcCBpbiBkYXRhIHByZXByb2Nlc3NpbmcgdGhhdCBlbmFibGVzIHRoZSB1c2Ugb2YgY2F0ZWdvcmljYWwgZGF0YSBpbiB2YXJpb3VzIGRhdGEgYW5hbHlzaXMgYW5kIG1hY2hpbmUgbGVhcm5pbmcgdGFza3MsIHdlIGVuY29kZWQgYXR0cmlidXRlcyBsaWtlIHRoZSAncGFyZW50IHdhcyBpbiBjb2xsZWdlJyBhdHRyaWJ1dGUgZnJvbSAoVHJ1ZSwgRmFsc2UpIHRvICgxLCAwKSwgYW5kICd3aWxsIGdvIHRvIGNvbGxlZ2UnIGZyb20gKFRydWUsIEZhbHNlKSB0byAoMCwgMSkuIFRoaXMgZW5jb2RpbmcgaXMgY2FycmllZCBvdXQgYXMgd2UgYWltIHRvIHByZWRpY3QgdGhlIGluZmx1ZW5jaW5nIGZhY3RvcnMuIEFkZGl0aW9uYWxseSwgd2UgZW5jb2RlZCB0aGUgJ2dlbmRlcicgYXR0cmlidXRlIGZyb20gKEZlbWFsZSwgTWFsZSkgdG8gKDEsIDApLCAnc2Nob29sIGFjY3JlZGl0YXRpb24nIGZyb20gKEEsIEIpIHRvICgxLCAwKSwgJ3R5cGVfc2Nob29sJyBmcm9tIChBY2FkZW1pYywgVm9jYXRpb25hbCkgdG8gKDEsIDApLCAncmVzaWRlbmNlJyBmcm9tIChVcmJhbiwgUnVyYWwpIHRvICgxLCAwKSwgYW5kICdpbnRlcmVzdCcgZnJvbSAoVmVyeSBpbnRlcmVzdGVkICxJbnRlcmVzdGVkICwgTGVzcyBJbnRlcmVzdGVkICwgTm90IEludGVyZXN0ZWQgLFVuY2VydGFpbiApIHRvICg0LDMsMiwgMSwgMCkgcmVzcGVjdGl2ZWx5LiBFbmNvZGluZyBzZXJ2ZXMgdG8gc2ltcGxpZnkgdGhlIGRhdGEsIHJlZHVjZSBjb21wbGV4aXR5LCBhbmQgZW5oYW5jZSBpdHMgc3VpdGFiaWxpdHkgZm9yIG1vZGVsaW5nIHB1cnBvc2VzLg0KDQojIyBDb3JyZWxhdGlvbiBhbmFseXNpcyBDaGkgc3F1YXJlIHRlc3QgZm9yIG5vbWluYWwgYXR0cmlidXRlOg0KDQpgYGB7cn0NCg0KIzENCkM9Y2hpc3EudGVzdChEYXRhc2V0JHR5cGVfc2Nob29sICwgRGF0YXNldCR3aWxsX2dvX3RvX2NvbGxlZ2UpDQpwcmludChDKQ0KIzINCg0KQz1jaGlzcS50ZXN0KERhdGFzZXQkc2Nob29sX2FjY3JlZGl0YXRpb24gLCBEYXRhc2V0JHdpbGxfZ29fdG9fY29sbGVnZSkNCnByaW50KEMpDQojMw0KQz1jaGlzcS50ZXN0KERhdGFzZXQkZ2VuZGVyICwgRGF0YXNldCR3aWxsX2dvX3RvX2NvbGxlZ2UpDQpwcmludChDKQ0KIzQNCkM9Y2hpc3EudGVzdChEYXRhc2V0JGludGVyZXN0ICwgRGF0YXNldCR3aWxsX2dvX3RvX2NvbGxlZ2UpDQpwcmludChDKQ0KDQojNQ0KQz1jaGlzcS50ZXN0KERhdGFzZXQkcmVzaWRlbmNlICwgRGF0YXNldCR3aWxsX2dvX3RvX2NvbGxlZ2UpDQpwcmludChDKQ0KDQojNg0KQz1jaGlzcS50ZXN0KERhdGFzZXQkYXZlcmFnZV9ncmFkZXMgLCBEYXRhc2V0JHdpbGxfZ29fdG9fY29sbGVnZSkNCnByaW50KEMpDQoNCiM3DQpDPWNoaXNxLnRlc3QoRGF0YXNldCRwYXJlbnRfd2FzX2luX2NvbGxlZ2UgLCBEYXRhc2V0JHdpbGxfZ29fdG9fY29sbGVnZSkNCnByaW50KEMpDQpgYGANCg0KQWxsIHRoZSBhdHRyaWJ1dGVzIGhhdmUgWC1zcXVhcmUgZ3JlYXRlciB0aGFuIHRoZSBwLXZhbHVlIHdoaWNoIGluZGljYXRlIGEgc29tZSBhc3NvY2lhdGlvbiB3aXRoIHRoZSBjbGFzcyBsYWJlbDsgdGhlcmVmb3JlIHdlIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzDQoNCndlIG5vdGljZWQgZm9yICdpbnRlcmVzdCcgYW5kICdhdmVyYWdlIGdyYWRlJyB0aGUgYW5hbHlzaXMgc2hvd3MgdGhhdCBYLXNxdWFyZSBpcyBtdWNoIGxhcmdlciB0aGFuIHAtdmFsdWUgaW5kaWNhdGUgdGhlIHNpZ25pZmljYW50IGFzc29jaWF0aW9uIG9mIHRoZSB0d28gYXR0cmlidXRlcyB3aXRoIHRoZSBkZWNpc2lvbiBvZiB0aGUgc3R1ZGVudCB0byBnbyB0byB0aGUgY29sbGFnZSBvciBub3QNCg0KIyMgQ29ycmVsYXRpb24gY29lZmZpY2llbnQgYW5hbHlzaXMgZm9yIG51bWVyaWMgYXR0cmlidXRlOg0KDQpgYGB7cn0NCg0KYmlzZXJpYWwuY29yKERhdGFzZXQkcGFyZW50X3NhbGFyeSxEYXRhc2V0JHdpbGxfZ29fdG9fY29sbGVnZSwgYygiYWxsLm9icyIsICJjb21wbGV0ZS5vYnMiKSwgbGV2ZWwgPSAxKQ0KYmlzZXJpYWwuY29yKERhdGFzZXQkaG91c2VfYXJlYSxEYXRhc2V0JHdpbGxfZ29fdG9fY29sbGVnZSwgYygiYWxsLm9icyIsICJjb21wbGV0ZS5vYnMiKSwgbGV2ZWwgPSAxKQ0KYmlzZXJpYWwuY29yKERhdGFzZXQkcGFyZW50X2FnZSxEYXRhc2V0JHdpbGxfZ29fdG9fY29sbGVnZSxjKCJhbGwub2JzIiwgImNvbXBsZXRlLm9icyIpLCBsZXZlbCA9IDEpDQogDQogDQoNCmBgYA0KDQp0aGUgYW5hbHlzaXMgc2hvd3MgbW9kZXJhdGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgZm9yIHBhcmVudCBzYWxhcnkgYW5kIGhvdXNlIGFyZWEgd2l0aCB0aGUgY2xhc3MgbGFiZWwgd2hpY2ggaW5kaWNhdGUgdGhhdCB0aGV5IGFyZSByZWxldmFudCBmYWN0b3JzIG1lYW5pbmcgdGhhdCB0aGUgaGlnaGVyIHRoZSBwYXJlbnQgc2FsYXJ5IGFuZCB0aGUgbGFyZ2VyIGhvdXNlIGFyZWEgdGhlIGhpZ2hlciBwcm9iYWJpbGl0eSBmb3IgYSBzdHVkZW50IHRvIGVucm9sbCBpbiBhIGNvbGxhZ2UNCg0Kd2hlcmUgaXMgdGhlIG9uIG90aGVyIGhhbmQsIHRoZSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBmb3IgdGhlIHBhcmVudCBhZ2UgaXMgdmVyeSBzbWFsbCB3aGljaCBpbmRpY2F0ZSB0aGF0IHRoZSBwYXJlbnQgYWdlIGhhcyBsaXR0bGUgaW1wYWN0IHRvIHRoZSBwcm9iYWJpbGl0eSBmb3Igc3R1ZGVudCB0byBlbnJvbGwgaW4gYSBjb2xsYWdlDQoNCiMjIEZlYXR1cmUgc2VsZWN0aW9uOg0KDQp1bHRpbWF0ZWx5IGJhc2VkIG9uIHRoZSBhbmFseXNpcyBvZiB0aGUgY29ycmVsYXRpb24gdGhhdCB3ZSBjb25kdWN0ZWQgb24gdGhlIHJlbGF0aW9uc2hpcCBvZiB0aGUgZGF0YXNldCBhdHRyaWJ1dGVzIHdpdGggdGhlIGNsYXNzIGxhYmVsLCBhbmQgdGhlIHVuZGVyc3RhbmRpbmcgb2YgdGhlIGRhdGEgYW5kIHRoZSBjb250ZXh0IG9mIGVhY2ggYXR0cmlidXRlIGFuZCBwb3RlbnRpYWwgcmVsZXZhbmNlIHRvIHRoZSBjbGFzcyBsYWJlbCB3ZSBkZWNpZGVkIHRvIG5vdCBkZWxldGUgYW55IG9mIHRoZSBhdHRyaWJ1dGUNCg0KIyMgQ2xhc3NpZmljYXRpb246DQoNCiMjIyBmYWN0b3IgdGhlIGRhdGENCg0KYGBge3J9DQoNCmRhdGEgPC0gUHJlcHJvY2Vzc2VkX2RhdGFzZXQNCg0KDQpkYXRhJHdpbGxfZ29fdG9fY29sbGVnZSA8LSBhcy5mYWN0b3IoZGF0YSR3aWxsX2dvX3RvX2NvbGxlZ2UpDQpkYXRhJHJlc2lkZW5jZSA8LSBhcy5mYWN0b3IoZGF0YSRyZXNpZGVuY2UpDQpkYXRhJGdlbmRlciA8LSBhcy5mYWN0b3IoZGF0YSRnZW5kZXIpDQpkYXRhJHBhcmVudF93YXNfaW5fY29sbGVnZSA8LSBhcy5mYWN0b3IoZGF0YSRwYXJlbnRfd2FzX2luX2NvbGxlZ2UpDQpkYXRhJGludGVyZXN0IDwtIGFzLmZhY3RvcihkYXRhJGludGVyZXN0KQ0KZGF0YSR0eXBlX3NjaG9vbCA8LSBhcy5mYWN0b3IoZGF0YSR0eXBlX3NjaG9vbCkNCmRhdGEkc2Nob29sX2FjY3JlZGl0YXRpb24gPC0gYXMuZmFjdG9yKGRhdGEkc2Nob29sX2FjY3JlZGl0YXRpb24pDQoNCmRhdGEkYXZlcmFnZV9ncmFkZXMgPC0gYXMuZmFjdG9yKGRhdGEkYXZlcmFnZV9ncmFkZXMpDQpzdHIoZGF0YSkNCg0KYGBgDQoNCiMjIyBiYWxhbmNlZCBvciBpbWJhbGFuY2VkDQoNCmBgYHtyfQ0KDQpsaWJyYXJ5KHRpZHl2ZXJzZSkgDQpsaWJyYXJ5KGNhcmV0KQ0KZGF0YSR3aWxsX2dvX3RvX2NvbGxlZ2U8LSBhcy5udW1lcmljKGRhdGEkd2lsbF9nb190b19jb2xsZWdlKQ0KaGlzdChkYXRhJHdpbGxfZ29fdG9fY29sbGVnZSxjb2w9ImNvcmFsIikNCnByb3AudGFibGUodGFibGUoZGF0YSR3aWxsX2dvX3RvX2NvbGxlZ2UpKQ0KYGBgDQoNCndlIHdhbnQgdG8gY29uZmlybSB0aGF0IHRoZSBkaXN0cmlidXRpb24gYmV0d2VlbiB0aGUgdHdvIGxhYmVsIGRhdGEgaXMgbm90IHRvbyBtdWNoIGRpZmZlcmVudC4gQmVjYXVzZSBpbWJhbGFuY2VkIGRhdGFzZXRzIGNhbiBsZWFkIHRvIGltYmFsYW5jZWQgYWNjdXJhY3kuDQoNCkZvcnR1bmF0ZWx5ICxvdXIgZGF0YSBpcyBiYWxhbmNlZA0KDQojIyMgcGFydGl0aW9uIG1ldGhvZA0KDQpXZSBvcHRlZCBmb3IgY3Jvc3MtdmFsaWRhdGlvbiBhcyBvdXIgcGFydGl0aW9uIG1ldGhvZCBvd2luZyB0byB0aGUgY29uc3RyYWludHMgcG9zZWQgYnkgbGltaXRlZCBkYXRhIGF2YWlsYWJpbGl0eS4gVG8gZW5zdXJlIHJvYnVzdG5lc3MgaW4gb3VyIGV2YWx1YXRpb24sIHdlIGVtcGxveWVkIHRocmVlIGRpc3RpbmN0IHZhbHVlcyBmb3IgayBmb2xkcyAyLCAzLCBhbmQgNC4gd2UgY2hvc2Ugc21hbGwgayBmb2xkcyBiZWNhdXNlIG9mIG91ciBzbWFsbCBkYXRhDQoNCiMjIyBjNC41DQoNCmBgYHtyfQ0KbGlicmFyeShjYXJldCkNCmxpYnJhcnkocnBhcnQpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShycGFydC5wbG90KQ0KDQpzZXQuc2VlZCgxMjMpDQpmb2xkIDwtIGMoMiwgMywgNCkgICMgVmFsdWVzIG9mIHh2YWwgKG51bWJlciBvZiBmb2xkcykgdG8gdHJ5DQoNCmZvciAoZm9sZCBpbiBmb2xkKSB7DQogIGNhdCgiZm9sZCA9IiwgZm9sZCwgIlxuIikNCiAgdHJjdHJsIDwtIHRyYWluQ29udHJvbChtZXRob2QgPSAiY3YiLCBudW1iZXIgPSBmb2xkLCBzYXZlUHJlZGljdGlvbnMgPSBUUlVFKQ0KICBjNDVfZml0IDwtIHRyYWluKGZhY3Rvcih3aWxsX2dvX3RvX2NvbGxlZ2UpIH4gLiwgZGF0YSA9IGRhdGEsIG1ldGhvZCA9ICJKNDgiLCB0ckNvbnRyb2wgPSB0cmN0cmwpDQogICBwcmludChjNDVfZml0JGZpbmFsTW9kZWwpDQogICMgR2V0IHByZWRpY3RlZCB2YWx1ZXMNCiAgcHJlZGljdGlvbnMgPC0gcHJlZGljdChjNDVfZml0LCBuZXdkYXRhID0gZGF0YSkNCiAgDQogICMgQ3JlYXRlIGNvbmZ1c2lvbiBtYXRyaXgNCiAgY29uZnVzaW9uX21hdHJpeCA8LSBjb25mdXNpb25NYXRyaXgocHJlZGljdGlvbnMsIGRhdGEkd2lsbF9nb190b19jb2xsZWdlKQ0KICANCiAgIyBQcmludCB0aGUgY29uZnVzaW9uIG1hdHJpeA0KICBwcmludChjb25mdXNpb25fbWF0cml4KQ0KICANCiAgIyBQcmludCBhY2N1cmFjeSBmb3IgZWFjaCBmb2xkDQogIHByZWQgPC0gYzQ1X2ZpdCRwcmVkDQogIHByZWQkZXF1YWwgPC0gaWZlbHNlKHByZWQkcHJlZCA9PSBwcmVkJG9icywgMSwgMCkNCiAgZWFjaGZvbGQgPC0gcHJlZCAlPiUNCiAgICBncm91cF9ieShSZXNhbXBsZSkgJT4lDQogICAgc3VtbWFyaXNlX2F0KHZhcnMoZXF1YWwpLA0KICAgICAgICAgICAgICAgICBsaXN0KEFjY3VyYWN5ID0gbWVhbikpDQogIHByaW50KGVhY2hmb2xkKQ0KICAgICMgUGxvdCBkZWNpc2lvbiB0cmVlDQpwbG90KGM0NV9maXQkZmluYWxNb2RlbCwgbWFpbiA9IGZvbGQpDQogIA0KfQ0KYGBgDQoNClRoZSBnYWluIHJhdGlvIGNvbnNpc3RlbnRseSBmYXZvcnMgdW5iYWxhbmNlZCBzcGxpdHMsIGFzIGRlbW9uc3RyYXRlZCBieSBpdHMgc2VsZWN0aW9uIG9mICJQYXJlbnQgc2FsYXJ5IiBhcyB0aGUgcm9vdCBmb3IgYWxsIHRocmVlIHRyZWVzIGV2ZW4gdGhvdWdoIGl0J3Mgc2hvd24gaW4gdGhlIHRyZWUgImF2ZXJhZ2UgZ3JhZGVzIiBhcyB0aGUgcm9vdCBidXQgdGhlIHNwbGl0IHBvaW50J3MgdGhhdCBhbGwgdGhlIHZhbHVlIGluIG9uZSBkaXJhY3Rpb24gLiBJbiB0aGlzIGNvbmZpZ3VyYXRpb24sIG9uZSBwYXJ0aXRpb24gaXMgbm90YWJseSBzbWFsbGVyIHRoYW4gdGhlIG90aGVycywgYW5kIHRoZSBmZWF0dXJlIGV4aGliaXRzIGEgaGlnaGVyIG51bWJlciBvZiBkaXN0aW5jdCB2YWx1ZXMuIERlc3BpdGUgdGhlIGZhY3QgdGhhdCB0aGUgbm9kZSBjb3JyZXNwb25kaW5nIHRvICJQYXJlbnQgYWdlIiwgInBhcmVudCB3YXMgaW4gY29sbGFnZSIgaXMgbm90IHB1cmUsIHRoZSByZXN1bHRpbmcgdHJlZXMgZXhoaWJpdCBpbXByZXNzaXZlIGFjY3VyYWN5IGxldmVscywgYWxsIHN1cnBhc3NpbmcgOTQlDQoNCiMjIyBjYXJ0DQoNCmBgYHtyfQ0KbGlicmFyeShjYXJldCkNCmxpYnJhcnkocnBhcnQpDQpsaWJyYXJ5KHJwYXJ0LnBsb3QpDQoNCg0KDQpzZXQuc2VlZCgxMjM0KSAjIFJhbmRvbSBzZWVkDQpmb2xkIDwtIGMoMiwgMywgNCkgICMgVmFsdWVzIG9mIHh2YWwgKG51bWJlciBvZiBmb2xkcykgdG8gdHJ5DQoNCmZvciAoZm9sZCBpbiBmb2xkKSB7DQpjYXQoImZvbGQiPWZvbGQpDQp0cmN0cmwgPC0gdHJhaW5Db250cm9sKG1ldGhvZCA9ICJjdiIsIG51bWJlciA9IGZvbGQsIHNhdmVQcmVkaWN0aW9ucyA9IFRSVUUpDQpkdF9maXQgPC0gdHJhaW4oZmFjdG9yKHdpbGxfZ29fdG9fY29sbGVnZSkgfiAuLCBkYXRhID0gZGF0YSwgbWV0aG9kID0gInJwYXJ0MVNFIiwgdHJDb250cm9sID0gdHJjdHJsKQ0KDQogIyBQbG90IGRlY2lzaW9uIHRyZWUNCiAgcnBhcnQucGxvdChkdF9maXQkZmluYWxNb2RlbCkNCiAgDQojIEdldCBwcmVkaWN0ZWQgdmFsdWVzDQpwcmVkaWN0aW9ucyA8LSBwcmVkaWN0KGR0X2ZpdCwgbmV3ZGF0YSA9IGRhdGEpDQoNCiMgQ3JlYXRlIGNvbmZ1c2lvbiBtYXRyaXgNCmNvbmZ1c2lvbl9tYXRyaXggPC0gY29uZnVzaW9uTWF0cml4KHByZWRpY3Rpb25zLCBkYXRhJHdpbGxfZ29fdG9fY29sbGVnZSkNCg0KIyBQcmludCB0aGUgY29uZnVzaW9uIG1hdHJpeA0KcHJpbnQoY29uZnVzaW9uX21hdHJpeCkNCg0KI3ByaW50IGVhY2ggZmxvZA0KcHJlZCA8LSBkdF9maXQkcHJlZA0KcHJlZCRlcXVhbCA8LSBpZmVsc2UocHJlZCRwcmVkID09IHByZWQkb2JzLCAxLDApDQplYWNoZm9sZCA8LSBwcmVkICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgZ3JvdXBfYnkoUmVzYW1wbGUpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICANCiAgc3VtbWFyaXNlX2F0KHZhcnMoZXF1YWwpLCAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgbGlzdChBY2N1cmFjeSA9IG1lYW4pKSAgICAgICAgICAgICAgDQpwcmludChlYWNoZm9sZCAgKQ0KDQogIH0NCmBgYA0KDQphdmVyYWdlcyBncmFkZSBleGhpYml0cyB0aGUgc21hbGxlc3QgR2luaSBpbmRleCBiaW5hcnkgc3BsaXQsIHNpZ25pZnlpbmcgYSBzdWJzdGFudGlhbCByZWR1Y3Rpb24gaW4gaW1wdXJpdHkuIEhlbmNlLCBpdCBpcyBjaG9zZW4gYXMgdGhlIHNwbGl0dGluZyBhdHRyaWJ1dGUuIENvbnZlcnNlbHksIGF0dHJpYnV0ZXMgc3VjaCBhcyAndHlwZV9zY2hvb2wsJyAnc2Nob29sX2FjY3JlZGl0YXRpb24sJyAnZ2VuZGVyLCcgJ3BhcmVudF9hZ2UsJyBhbmQgJ3BhcmVudF93YXNfaW5fY29sbGVnZScgeWllbGQgbWluaW1hbCBpbXB1cml0eSByZWR1Y3Rpb24sIGxlYWRpbmcgdG8gdGhlaXIgZXhjbHVzaW9uIGZyb20gdGhlIHRyZWUuIFRoZSBkYXRhc2V0J3MgYmFsYW5jZWQgY2xhc3MgbGFiZWxzIGFuZCBtYXJnaW5hbCBkaWZmZXJlbmNlcyBpbiBhY2N1cmFjeSBhY3Jvc3MgZm9sZHMgcmVzdWx0IGluIGNvbnNpc3RlbnQgdHJlZSBzdHJ1Y3R1cmVzLCBhcyBldmlkZW5jZWQgYnkgdGhlIGlkZW50aWNhbCB0cmVlcyBpbiBhbGwgZm9sZHMuIEZvciBmdXJ0aGVyIGRldGFpbHMsIHJlZmVyIHRvIHRoZSBbaW5kZXhdLiBPdmVyYWxsLCB0aGUgbW9kZWwgYXR0YWlucyBhbiA4NiUgYWNjdXJhY3ksIGVtcGhhc2l6aW5nIGl0cyBlZmZlY3RpdmVuZXNzLg0KDQojIyMgSUQzDQoNCmBgYHtyfQ0KbGlicmFyeShjYXJldCkNCmxpYnJhcnkocGFydHlraXQpDQpsaWJyYXJ5KGRwbHlyKQ0KDQpmb2xkIDwtIGMoNCwgMywgMikgICMgVmFsdWVzIG9mIHh2YWwgKG51bWJlciBvZiBmb2xkcykgdG8gdHJ5DQoNCmZvciAoZm9sZCBpbiBmb2xkKSB7DQogIGNhdCgiZm9sZCA9IiwgZm9sZCwgIlxuIikNCiAgdHJjdHJsIDwtIHRyYWluQ29udHJvbChtZXRob2QgPSAiY3YiLCBudW1iZXIgPSBmb2xkLCBzYXZlUHJlZGljdGlvbnMgPSBUUlVFKQ0KICANCiAgaWRfZml0IDwtIHRyYWluKGZhY3Rvcih3aWxsX2dvX3RvX2NvbGxlZ2UpIH4gLiwgZGF0YSA9IGRhdGEsIG1ldGhvZCA9ICJjdHJlZSIsIHRyQ29udHJvbCA9IHRyY3RybCkNCiAgIHByaW50KGlkX2ZpdCRmaW5hbE1vZGVsKQ0KICAjIEdldCBwcmVkaWN0ZWQgdmFsdWVzDQogIHByZWRpY3Rpb25zIDwtIHByZWRpY3QoaWRfZml0LCBuZXdkYXRhID0gZGF0YSkNCiAgDQogICMgQ3JlYXRlIGNvbmZ1c2lvbiBtYXRyaXgNCiAgY29uZnVzaW9uX21hdHJpeCA8LSBjb25mdXNpb25NYXRyaXgocHJlZGljdGlvbnMsIGRhdGEkd2lsbF9nb190b19jb2xsZWdlKQ0KICANCiAgIyBQcmludCB0aGUgY29uZnVzaW9uIG1hdHJpeA0KICBwcmludChjb25mdXNpb25fbWF0cml4KQ0KICANCiAgIyBQcmludCBhY2N1cmFjeSBmb3IgZWFjaCBmb2xkDQogIHByZWQgPC0gaWRfZml0JHByZWQNCiAgcHJlZCRlcXVhbCA8LSBpZmVsc2UocHJlZCRwcmVkID09IHByZWQkb2JzLCAxLCAwKQ0KICBlYWNoZm9sZCA8LSBwcmVkICU+JQ0KICAgIGdyb3VwX2J5KFJlc2FtcGxlKSAlPiUNCiAgICBzdW1tYXJpc2VfYXQodmFycyhlcXVhbCksIGxpc3QoQWNjdXJhY3kgPSBtZWFuKSkNCiAgcHJpbnQoZWFjaGZvbGQpDQoNCiAgIyBQbG90IGRlY2lzaW9uIHRyZWUNCiAgcGxvdChpZF9maXQkZmluYWxNb2RlbCwgbWFpbiA9IHBhc3RlKCJEZWNpc2lvbiBUcmVlIChGb2xkIiwgZm9sZCwgIikiKSkNCiAgDQp9DQpgYGANCg0KQWRkaXRpb25hbCBpbnNpZ2h0cyByZXZlYWwgdGhhdCBhdHRyaWJ1dGVzIHN1Y2ggYXMgc2Nob29sIGFjY3JlZGl0YXRpb24sIHBhcmVudCB3YXMgaW4gY29sbGFnZSBjb250cmlidXRlIHRvIGhpZ2ggaW1wdXJpdHkuIEluIGNvbnRyYXN0LCBQYXJlbnQgc2FsYXJ5IGlzIGNob3NlbiBhcyB0aGUgcm9vdCBkdWUgdG8gaXRzIGhpZ2ggcHVyaXR5LiBHaXZlbiB0aGUgYmFsYW5jZWQgY2xhc3MgbGFiZWxzIGluIG91ciBkYXRhc2V0IGFuZCBtaW5pbWFsIHZhcmlhdGlvbnMgaW4gYWNjdXJhY3kgYWNyb3NzIGZvbGRzLCB0aGUgcmVzdWx0IHlpZWxkcyBjb25zaXN0ZW50IHRyZWUgc3RydWN0dXJlcywgd2l0aCBvbmx5IHR3byBkaXN0aW5jdCB0cmVlcyBvYnNlcnZlZCBmb3IgYWxsIGZvbGRzLiBGb3IgZnVydGhlciBkZXRhaWxzLCBwbGVhc2UgcmVmZXIgdG8gdGhlIFtpbmRleF0uIFRoZSBvdmVyYWxsIGFjY3VyYWN5IGNvbnNpc3RlbnRseSBzdXJwYXNzZXMgODYlLCBhZmZpcm1pbmcgdGhlIG1vZGVsJ3MgZWZmaWNhY3kNCg0KIyMjIGZpbmFsIGFuYWx5c2lzDQoNClRoZSBDNC41IG1vZGVsIGVtZXJnZWQgYXMgdGhlIHRvcC1wZXJmb3JtaW5nIGV2YWx1YXRpb24gbW9kZWwsIGFjaGlldmluZyBhbiBpbXByZXNzaXZlIGFjY3VyYWN5IHJhdGUgb2YgOTQlIHRvIDk3JS4gSXQgd2FzIGZvbGxvd2VkIGJ5IHRoZSBJRDMgbW9kZWwsIHdoaWNoIGRlbW9uc3RyYXRlZCBzbGlnaHRseSBsb3dlciBhY2N1cmFjeSByYW5naW5nIGZyb20gODYlIHRvIDg5JS4gTGFzdGx5LCB0aGUgY2FydCBtb2RlbCBleGhpYml0ZWQgYW4gYWNjdXJhY3kgcmF0ZSBvZiA4NiUuDQoNCnRoZSBDNC41IGdhdmUgYmV0dGVyIHJlc3VsdCB0aGFuIElEMyBhbmQgQ2FydCBiZWNhdXNlIHRoZXkgYm90aCBhcmUgYmlhc2VkIHRvIG11bHRpdmFsdWVkIHdoZXJlIEM0LjUgbm9ybWFsaXplZCBwYXJlbnQgc2FsYXJ5IGFuZCBob3VzZSBhcmVhIHdoaWNoIGFyZSBtdWx0aXZhbHVlIGF0dHJpYnV0ZXMNCg0KQzQuNSBhbmQgSUQzIG1vZGVscywgdGhlIHBhcmVudCdzIHNhbGFyeSBzZXJ2ZWQgYXMgdGhlIHJvb3QgZmVhdHVyZSwgaW5kaWNhdGluZyB0aGF0IHRoZSBmaW5hbmNpYWwgY2lyY3Vtc3RhbmNlcyBvZiB0aGUgc3R1ZGVudCBhcmUgYSBjcnVjaWFsIGZhY3RvciBmb3IgY29udGVtcG9yYXJ5IHVuaXZlcnNpdGllcy4NCg0KIyMgaW5kZXgNCg0KIyMjIGFsbCB0cmVlcyBvZiBDNC41DQoNCmBgYHtyfQ0KbGlicmFyeShjYXJldCkNCmxpYnJhcnkocnBhcnQpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShycGFydC5wbG90KQ0KDQpmb2xkcyA8LSBjKDIsIDMsIDQpICAjIFZhbHVlcyBvZiB4dmFsIChudW1iZXIgb2YgZm9sZHMpIHRvIHRyeQ0KDQpmb3IoZm9sZHMgaW4gZm9sZHMpeyANCiAgY2F0KCJmb2xkID0iLCBmb2xkX3ZhbCwgIlxuIikNCmZvciAoZm9sZF92YWwgaW4gMTpmb2xkcykgew0KIA0KICANCiAgdHJjdHJsIDwtIHRyYWluQ29udHJvbChtZXRob2QgPSAiY3YiLCBudW1iZXIgPSBmb2xkX3ZhbCwgc2F2ZVByZWRpY3Rpb25zID0gVFJVRSkNCiAgYzQ1X2ZpdCA8LSB0cmFpbihmYWN0b3Iod2lsbF9nb190b19jb2xsZWdlKSB+IC4sIGRhdGEgPSBkYXRhLCBtZXRob2QgPSAiSjQ4IiwgdHJDb250cm9sID0gdHJjdHJsKQ0KICANCiAgIHBsb3QoYzQ1X2ZpdCRmaW5hbE1vZGVsLCBtYWluID0gcGFzdGUoIkRlY2lzaW9uIFRyZWUgLSBGb2xkIiwgZm9sZF92YWwpKQ0KfQ0KICAjIEdldCBwcmVkaWN0ZWQgdmFsdWVzDQogIHByZWRpY3Rpb25zIDwtIHByZWRpY3QoYzQ1X2ZpdCwgbmV3ZGF0YSA9IGRhdGEpDQogIA0KICAjIENyZWF0ZSBjb25mdXNpb24gbWF0cml4DQogIGNvbmZ1c2lvbl9tYXRyaXggPC0gY29uZnVzaW9uTWF0cml4KHByZWRpY3Rpb25zLCBkYXRhJHdpbGxfZ29fdG9fY29sbGVnZSkNCiAgDQogICMgUHJpbnQgdGhlIGNvbmZ1c2lvbiBtYXRyaXgNCiAgcHJpbnQoY29uZnVzaW9uX21hdHJpeCkNCiAgDQogICMgUHJpbnQgYWNjdXJhY3kgZm9yIGVhY2ggZm9sZA0KICBwcmVkIDwtIGM0NV9maXQkcHJlZA0KICBwcmVkJGVxdWFsIDwtIGlmZWxzZShwcmVkJHByZWQgPT0gcHJlZCRvYnMsIDEsIDApDQogIGVhY2hmb2xkIDwtIHByZWQgJT4lDQogICAgZ3JvdXBfYnkoUmVzYW1wbGUpICU+JQ0KICAgIHN1bW1hcmlzZV9hdCh2YXJzKGVxdWFsKSwNCiAgICAgICAgICAgICAgICAgbGlzdChBY2N1cmFjeSA9IG1lYW4pKQ0KICBwcmludChlYWNoZm9sZCkNCiAgDQogICMgUGxvdCBkZWNpc2lvbiB0cmVlIGZvciBlYWNoIGZvbGQNCiANCg0KfQ0KYGBgDQoNCiMjIyBhbGwgdHJlZXMgb2YgSUQzDQoNCmBgYHtyfQ0KbGlicmFyeShjYXJldCkNCmxpYnJhcnkocGFydHlraXQpDQpsaWJyYXJ5KGRwbHlyKQ0KDQpmb2xkIDwtIGMoNCwgMywgMikgICMgVmFsdWVzIG9mIHh2YWwgKG51bWJlciBvZiBmb2xkcykgdG8gdHJ5DQoNCmZvciAoZm9sZCBpbiBmb2xkKSB7DQogICBjYXQoImZvbGQgPSIsIGZvbGQsICJcbiIpDQogIGZvcihpIGluIDE6Zm9sZCl7DQogIHRyY3RybCA8LSB0cmFpbkNvbnRyb2wobWV0aG9kID0gImN2IiwgbnVtYmVyID0gZm9sZCwgc2F2ZVByZWRpY3Rpb25zID0gVFJVRSkNCiAgDQogIGlkX2ZpdCA8LSB0cmFpbihmYWN0b3Iod2lsbF9nb190b19jb2xsZWdlKSB+IC4sIGRhdGEgPSBkYXRhLCBtZXRob2QgPSAiY3RyZWUiLCB0ckNvbnRyb2wgPSB0cmN0cmwsIHN1YnNldCA9IHRyY3RybCRpbmRleGVzW1tpXV0pDQogIA0KICAgIHBsb3QoaWRfZml0JGZpbmFsTW9kZWwsIG1haW4gPSBwYXN0ZSgiRGVjaXNpb24gVHJlZSAoRm9sZCIsIGZvbGQsIi0iLCBpLCAiKSIpKQ0KfQ0KICAgDQogICMgR2V0IHByZWRpY3RlZCB2YWx1ZXMNCiAgcHJlZGljdGlvbnMgPC0gcHJlZGljdChpZF9maXQsIG5ld2RhdGEgPSBkYXRhKQ0KICANCiAgIyBDcmVhdGUgY29uZnVzaW9uIG1hdHJpeA0KICBjb25mdXNpb25fbWF0cml4IDwtIGNvbmZ1c2lvbk1hdHJpeChwcmVkaWN0aW9ucywgZGF0YSR3aWxsX2dvX3RvX2NvbGxlZ2UpDQogIA0KICAjIFByaW50IHRoZSBjb25mdXNpb24gbWF0cml4DQogIHByaW50KGNvbmZ1c2lvbl9tYXRyaXgpDQogIA0KICAjIFByaW50IGFjY3VyYWN5IGZvciBlYWNoIGZvbGQNCiAgcHJlZCA8LSBpZF9maXQkcHJlZA0KICBwcmVkJGVxdWFsIDwtIGlmZWxzZShwcmVkJHByZWQgPT0gcHJlZCRvYnMsIDEsIDApDQogIGVhY2hmb2xkIDwtIHByZWQgJT4lDQogICAgZ3JvdXBfYnkoUmVzYW1wbGUpICU+JQ0KICAgIHN1bW1hcmlzZV9hdCh2YXJzKGVxdWFsKSwgbGlzdChBY2N1cmFjeSA9IG1lYW4pKQ0KICBwcmludChlYWNoZm9sZCkNCg0KICAjIFBsb3QgZGVjaXNpb24gdHJlZQ0KDQoNCn0NCmBgYA0KDQojIyMgYWxsIHRyZWVzIG9mIENhcnQNCg0KYGBge3J9DQpsaWJyYXJ5KGNhcmV0KQ0KbGlicmFyeShycGFydCkNCmxpYnJhcnkocnBhcnQucGxvdCkNCg0Kc2V0LnNlZWQoMTIzKSAjIFJhbmRvbSBzZWVkDQpmb2xkIDwtIGMoMiwgMywgNCkgICMgVmFsdWVzIG9mIHh2YWwgKG51bWJlciBvZiBmb2xkcykgdG8gdHJ5DQoNCmZvciAoZm9sZCBpbiBmb2xkKSB7DQogIGNhdCgiZm9sZCI9Zm9sZCkNCiAgZm9yKGkgaW4gMTpmb2xkKXsNCg0KdHJjdHJsIDwtIHRyYWluQ29udHJvbChtZXRob2QgPSAiY3YiLCBudW1iZXIgPSBmb2xkLCBzYXZlUHJlZGljdGlvbnMgPSBUUlVFKQ0KZHRfZml0IDwtIHRyYWluKGZhY3Rvcih3aWxsX2dvX3RvX2NvbGxlZ2UpIH4gLiwgZGF0YSA9IGRhdGEsIG1ldGhvZCA9ICJycGFydDFTRSIsIHRyQ29udHJvbCA9IHRyY3RybCkNCg0KICMgUGxvdCBkZWNpc2lvbiB0cmVlDQogIGNhdCgiRGVjaXNpb24gVHJlZSAtIEZvbGQiLCBpLCAiOlxuIikNCiAgcnBhcnQucGxvdChkdF9maXQkZmluYWxNb2RlbCkNCiAgDQp9DQojIEdldCBwcmVkaWN0ZWQgdmFsdWVzDQpwcmVkaWN0aW9ucyA8LSBwcmVkaWN0KGR0X2ZpdCwgbmV3ZGF0YSA9IGRhdGEpDQoNCiMgQ3JlYXRlIGNvbmZ1c2lvbiBtYXRyaXgNCmNvbmZ1c2lvbl9tYXRyaXggPC0gY29uZnVzaW9uTWF0cml4KHByZWRpY3Rpb25zLCBkYXRhJHdpbGxfZ29fdG9fY29sbGVnZSkNCg0KIyBQcmludCB0aGUgY29uZnVzaW9uIG1hdHJpeA0KcHJpbnQoY29uZnVzaW9uX21hdHJpeCkNCg0KI3ByaW50IGVhY2ggZmxvZA0KcHJlZCA8LSBkdF9maXQkcHJlZA0KcHJlZCRlcXVhbCA8LSBpZmVsc2UocHJlZCRwcmVkID09IHByZWQkb2JzLCAxLDApDQplYWNoZm9sZCA8LSBwcmVkICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgZ3JvdXBfYnkoUmVzYW1wbGUpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICANCiAgc3VtbWFyaXNlX2F0KHZhcnMoZXF1YWwpLCAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgbGlzdChBY2N1cmFjeSA9IG1lYW4pKSAgICAgICAgICAgICAgDQpwcmludChlYWNoZm9sZCAgKQ0KDQogIH0NCg0KYGBgDQoNCiMjIENsdXN0ZXJpbmcgKipBbmFseXNpczoqKg0KDQpJbiB0aGlzIGFuYWx5c2lzLCB3ZSBhcHBseSBLLW1lYW5zIGNsdXN0ZXJpbmcgdG8gdGhlIGRhdGFzZXQgdXNpbmcgZGlmZmVyZW50IHZhbHVlcyBvZiBLLiBLLW1lYW5zIGNsdXN0ZXJpbmcgaXMgYW4gdW5zdXBlcnZpc2VkIGxlYXJuaW5nIGFsZ29yaXRobSB0aGF0IHBhcnRpdGlvbnMgdGhlIGRhdGEgaW50byBLIGNsdXN0ZXJzIGJhc2VkIG9uIHNpbWlsYXJpdHkuIFdlIHdpbGwgZXhwbG9yZSB0aHJlZSBkaWZmZXJlbnQgdmFsdWVzIG9mIEsgYW5kIGV2YWx1YXRlIHRoZSBjbHVzdGVyaW5nIHJlc3VsdHMgdXNpbmcgdmFyaW91cyBtZXRyaWNzLg0KDQojIyMgUmVtb3ZpbmcgdGhlIGNsYXNzIGxhYmVsIGFuZCBwcmVwYXJpbmcgdGhlIGRhdGFzZXQgZm9yIENsdXN0ZXJpbmcNCg0KYGBge3J9DQogDQpvcmlnaW5hbF9kYXRhIDwtIFByZXByb2Nlc3NlZF9kYXRhc2V0DQoNCiMgUmVtb3ZlIGFueSBub24tbnVtZXJpYyBhdHRyaWJ1dGVzDQpudW1lcmljX2RhdGEgPC0gb3JpZ2luYWxfZGF0YVssIHNhcHBseShvcmlnaW5hbF9kYXRhLCBpcy5udW1lcmljKV0NCg0KIyBSZW1vdmUgdGhlIGNsYXNzIGxhYmVsICd3aWxsX2dvX3RvX2NvbGxlZ2UnDQpudW1lcmljX2RhdGEgPC0gbnVtZXJpY19kYXRhWywgIShuYW1lcyhudW1lcmljX2RhdGEpID09ICd3aWxsX2dvX3RvX2NvbGxlZ2UnKV0NCg0KDQojIFByaW50IHRoZSBkYXRhc2V0ICJudW1lcmljX2RhdGEiIHRvIG1ha2Ugc3VyZSBpdCdzIHByZXBhcmVkIGZvciBjbHVzdGVyaW5nDQpwcmludChudW1lcmljX2RhdGEpDQoNCiMgU2NhbGluZyB0aGUgZGF0YXNldA0KIyBudW1lcmljX2RhdGEgPC0gc2NhbGUobnVtZXJpY19kYXRhKQ0KDQogDQpgYGANCg0KTm93LCB0aGUgJ251bWVyaWNfZGF0YXNldCcgZGF0YXNldCBjb250YWlucyBvbmx5IG51bWVyaWMgYXR0cmlidXRlcyB3aXRob3V0IHRoZSBjbGFzcyBsYWJlbCwgd2hpY2ggbWFrZXMgaXQgcmVhZHkgZm9yIHRoZSBjbHVzdGVyaW5nIHByb2Nlc3MuDQoNCiMjIEs9Mg0KDQpgYGB7cn0NCiMgay1tZWFucyBjbHVzdGVyaW5nIHNldCBhIHNlZWQgZm9yIHJhbmRvbSBudW1iZXIgZ2VuZXJhdGlvbiB0byBtYWtlIHRoZSByZXN1bHRzIHJlcHJvZHVjaWJsZSANCnNldC5zZWVkKDg5NTMpDQoNCiMgcnVuIGttZWFucyBjbHVzdGVyaW5nIHRvIGZpbmQgMiBjbHVzdGVycw0Ka21lYW5zLnJlc3VsdCA8LSBrbWVhbnMobnVtZXJpY19kYXRhLCAyKQ0KDQojIHZpc3VhbGl6ZSBjbHVzdGVyaW5nDQpsaWJyYXJ5KGZhY3RvZXh0cmEpDQpmdml6X2NsdXN0ZXIoa21lYW5zLnJlc3VsdCwgZGF0YSA9IG51bWVyaWNfZGF0YSkNCg0KIyBwcmludCB0aGUgY2x1c3RlcmluZyByZXN1bHQNCnByaW50KGttZWFucy5yZXN1bHQpDQoNCg0KYGBgDQoNCiMjIyMgVGhlIFNpbGhvdWV0dGUgY29lZmZpY2llbnQNCg0KYGBge3J9DQojYXZlcmFnZSBmb3IgZWFjaCBjbHVzdGVyIA0KYXZnX3NpbCA8LSBzaWxob3VldHRlKGttZWFucy5yZXN1bHQkY2x1c3RlciwgZGlzdChudW1lcmljX2RhdGEpKSANCg0KI2stbWVhbnMgY2x1c3RlcmluZyB3aXRoIGVzdGltYXRpbmcgayBhbmQgaW5pdGlhbGl6YXRpb25zIA0KZnZpel9zaWxob3VldHRlKGF2Z19zaWwpDQoNCmBgYA0KDQojIyMjIFRoZSB0b3RhbCB3aXRoaW4tY2x1c3RlciBzdW0gb2Ygc3F1YXJlcw0KDQpgYGB7cn0NCiMgQ2FsY3VsYXRlIHRvdGFsIHdpdGhpbi1jbHVzdGVyIHN1bSBvZiBzcXVhcmVzDQp0b3RhbF93aXRoaW5zcyA8LSBrbWVhbnMucmVzdWx0JHRvdC53aXRoaW5zcw0KY2F0KCJUb3RhbCBXaXRoaW4tQ2x1c3RlciBTdW0gb2YgU3F1YXJlczoiLCBzdW0odG90YWxfd2l0aGluc3MpLCAiXG4iKQ0KDQp0cnVlX2xhYmVscyA8LSBjKDEsIDEsIDIsIDEsIDIsIDIsIDMsIDMsIDQsIDQpICAjIEFkanVzdCBiYXNlZCBvbiB5b3VyIGFjdHVhbCB0cnVlIGxhYmVscw0KDQpjbHVzdGVyX2Fzc2lnbm1lbnRzIDwtIGttZWFucy5yZXN1bHQkY2x1c3Rlcg0KIA0KYGBgDQoNCiMjIyMgQkN1YmVkIHJlY2FsbCBhbmQgcHJlY2lzaW9uDQoNCmBgYHtyfQ0KDQojIENhbGN1bGF0ZSBCQ3ViZWQgcHJlY2lzaW9uDQpwcmVjaXNpb24gPC0gMA0KZm9yIChpIGluIHVuaXF1ZSh0cnVlX2xhYmVscykpIHsNCiAgY2x1c3Rlcl9pbmRpY2VzIDwtIHdoaWNoKHRydWVfbGFiZWxzID09IGkpDQogIHByZWNpc2lvbiA8LSBwcmVjaXNpb24gKyBzdW0oKHRhYmxlKGNsdXN0ZXJfYXNzaWdubWVudHNbY2x1c3Rlcl9pbmRpY2VzXSkgKiAodGFibGUoY2x1c3Rlcl9hc3NpZ25tZW50c1tjbHVzdGVyX2luZGljZXNdKSAtIDEpKSAvIHN1bSh0YWJsZShjbHVzdGVyX2Fzc2lnbm1lbnRzW2NsdXN0ZXJfaW5kaWNlc10pKSkNCn0NCnByZWNpc2lvbiA8LSBwcmVjaXNpb24gLyBzdW0odGFibGUoY2x1c3Rlcl9hc3NpZ25tZW50cykpDQoNCiMgQ2FsY3VsYXRlIEJDdWJlZCByZWNhbGwNCnJlY2FsbCA8LSAwDQpmb3IgKGogaW4gdW5pcXVlKGNsdXN0ZXJfYXNzaWdubWVudHMpKSB7DQogIGNsdXN0ZXJfaW5kaWNlcyA8LSB3aGljaChjbHVzdGVyX2Fzc2lnbm1lbnRzID09IGopDQogIHJlY2FsbCA8LSByZWNhbGwgKyBzdW0oKHRhYmxlKHRydWVfbGFiZWxzW2NsdXN0ZXJfaW5kaWNlc10pICogKHRhYmxlKHRydWVfbGFiZWxzW2NsdXN0ZXJfaW5kaWNlc10pIC0gMSkpIC8gc3VtKHRhYmxlKHRydWVfbGFiZWxzW2NsdXN0ZXJfaW5kaWNlc10pKSkNCn0NCnJlY2FsbCA8LSByZWNhbGwgLyBzdW0odGFibGUodHJ1ZV9sYWJlbHMpKQ0KDQpjYXQoIkJDdWJlZCBQcmVjaXNpb246IiwgcHJlY2lzaW9uLCAiXG4iKQ0KY2F0KCJCQ3ViZWQgUmVjYWxsOiIsIHJlY2FsbCwgIlxuIikNCg0KDQpgYGANCg0KIyMgSz00DQoNCmBgYHtyfQ0KIyBrLW1lYW5zIGNsdXN0ZXJpbmcgc2V0IGEgc2VlZCBmb3IgcmFuZG9tIG51bWJlciBnZW5lcmF0aW9uIHRvIG1ha2UgdGhlIHJlc3VsdHMgcmVwcm9kdWNpYmxlIA0Kc2V0LnNlZWQoODk1MykNCg0KIyBydW4ga21lYW5zIGNsdXN0ZXJpbmcgdG8gZmluZCA0IGNsdXN0ZXJzDQprbWVhbnMucmVzdWx0IDwtIGttZWFucyhudW1lcmljX2RhdGEsIDQpDQoNCiMgdmlzdWFsaXplIGNsdXN0ZXJpbmcNCmxpYnJhcnkoZmFjdG9leHRyYSkNCmZ2aXpfY2x1c3RlcihrbWVhbnMucmVzdWx0LCBkYXRhID0gbnVtZXJpY19kYXRhKQ0KDQojIHByaW50IHRoZSBjbHVzdGVyaW5nIHJlc3VsdA0KcHJpbnQoa21lYW5zLnJlc3VsdCkNCg0KDQpgYGANCg0KIyMjIyBUaGUgU2lsaG91ZXR0ZSBjb2VmZmljaWVudA0KDQpgYGB7cn0NCiNhdmVyYWdlIGZvciBlYWNoIGNsdXN0ZXIgDQphdmdfc2lsIDwtIHNpbGhvdWV0dGUoa21lYW5zLnJlc3VsdCRjbHVzdGVyLCBkaXN0KG51bWVyaWNfZGF0YSkpIA0KDQojay1tZWFucyBjbHVzdGVyaW5nIHdpdGggZXN0aW1hdGluZyBrIGFuZCBpbml0aWFsaXphdGlvbnMgDQpmdml6X3NpbGhvdWV0dGUoYXZnX3NpbCkNCg0KYGBgDQoNCiMjIyMgVGhlIHRvdGFsIHdpdGhpbi1jbHVzdGVyIHN1bSBvZiBzcXVhcmVzDQoNCmBgYHtyfQ0KIyBDYWxjdWxhdGUgdG90YWwgd2l0aGluLWNsdXN0ZXIgc3VtIG9mIHNxdWFyZXMNCnRvdGFsX3dpdGhpbnNzIDwtIGttZWFucy5yZXN1bHQkdG90LndpdGhpbnNzDQpjYXQoIlRvdGFsIFdpdGhpbi1DbHVzdGVyIFN1bSBvZiBTcXVhcmVzOiIsIHN1bSh0b3RhbF93aXRoaW5zcyksICJcbiIpDQoNCnRydWVfbGFiZWxzIDwtIGMoMSwgMSwgMiwgMSwgMiwgMiwgMywgMywgNCwgNCkgICMgQWRqdXN0IGJhc2VkIG9uIHlvdXIgYWN0dWFsIHRydWUgbGFiZWxzDQoNCmNsdXN0ZXJfYXNzaWdubWVudHMgPC0ga21lYW5zLnJlc3VsdCRjbHVzdGVyDQogDQpgYGANCg0KIyMjIyBCQ3ViZWQgcmVjYWxsIGFuZCBwcmVjaXNpb24NCg0KYGBge3J9DQoNCiMgQ2FsY3VsYXRlIEJDdWJlZCBwcmVjaXNpb24NCnByZWNpc2lvbiA8LSAwDQpmb3IgKGkgaW4gdW5pcXVlKHRydWVfbGFiZWxzKSkgew0KICBjbHVzdGVyX2luZGljZXMgPC0gd2hpY2godHJ1ZV9sYWJlbHMgPT0gaSkNCiAgcHJlY2lzaW9uIDwtIHByZWNpc2lvbiArIHN1bSgodGFibGUoY2x1c3Rlcl9hc3NpZ25tZW50c1tjbHVzdGVyX2luZGljZXNdKSAqICh0YWJsZShjbHVzdGVyX2Fzc2lnbm1lbnRzW2NsdXN0ZXJfaW5kaWNlc10pIC0gMSkpIC8gc3VtKHRhYmxlKGNsdXN0ZXJfYXNzaWdubWVudHNbY2x1c3Rlcl9pbmRpY2VzXSkpKQ0KfQ0KcHJlY2lzaW9uIDwtIHByZWNpc2lvbiAvIHN1bSh0YWJsZShjbHVzdGVyX2Fzc2lnbm1lbnRzKSkNCg0KIyBDYWxjdWxhdGUgQkN1YmVkIHJlY2FsbA0KcmVjYWxsIDwtIDANCmZvciAoaiBpbiB1bmlxdWUoY2x1c3Rlcl9hc3NpZ25tZW50cykpIHsNCiAgY2x1c3Rlcl9pbmRpY2VzIDwtIHdoaWNoKGNsdXN0ZXJfYXNzaWdubWVudHMgPT0gaikNCiAgcmVjYWxsIDwtIHJlY2FsbCArIHN1bSgodGFibGUodHJ1ZV9sYWJlbHNbY2x1c3Rlcl9pbmRpY2VzXSkgKiAodGFibGUodHJ1ZV9sYWJlbHNbY2x1c3Rlcl9pbmRpY2VzXSkgLSAxKSkgLyBzdW0odGFibGUodHJ1ZV9sYWJlbHNbY2x1c3Rlcl9pbmRpY2VzXSkpKQ0KfQ0KcmVjYWxsIDwtIHJlY2FsbCAvIHN1bSh0YWJsZSh0cnVlX2xhYmVscykpDQoNCmNhdCgiQkN1YmVkIFByZWNpc2lvbjoiLCBwcmVjaXNpb24sICJcbiIpDQpjYXQoIkJDdWJlZCBSZWNhbGw6IiwgcmVjYWxsLCAiXG4iKQ0KDQoNCmBgYA0KDQojIyBLPTYNCg0KYGBge3J9DQojIGstbWVhbnMgY2x1c3RlcmluZyBzZXQgYSBzZWVkIGZvciByYW5kb20gbnVtYmVyIGdlbmVyYXRpb24gdG8gbWFrZSB0aGUgcmVzdWx0cyByZXByb2R1Y2libGUgDQpzZXQuc2VlZCg4OTUzKQ0KDQojIHJ1biBrbWVhbnMgY2x1c3RlcmluZyB0byBmaW5kIDYgY2x1c3RlcnMNCmttZWFucy5yZXN1bHQgPC0ga21lYW5zKG51bWVyaWNfZGF0YSwgNikNCg0KIyB2aXN1YWxpemUgY2x1c3RlcmluZw0KbGlicmFyeShmYWN0b2V4dHJhKQ0KZnZpel9jbHVzdGVyKGttZWFucy5yZXN1bHQsIGRhdGEgPSBudW1lcmljX2RhdGEpDQoNCiMgcHJpbnQgdGhlIGNsdXN0ZXJpbmcgcmVzdWx0DQpwcmludChrbWVhbnMucmVzdWx0KQ0KDQoNCmBgYA0KDQojIyMjIFRoZSBTaWxob3VldHRlIGNvZWZmaWNpZW50DQoNCmBgYHtyfQ0KI2F2ZXJhZ2UgZm9yIGVhY2ggY2x1c3RlciANCmF2Z19zaWwgPC0gc2lsaG91ZXR0ZShrbWVhbnMucmVzdWx0JGNsdXN0ZXIsIGRpc3QobnVtZXJpY19kYXRhKSkgDQoNCiNrLW1lYW5zIGNsdXN0ZXJpbmcgd2l0aCBlc3RpbWF0aW5nIGsgYW5kIGluaXRpYWxpemF0aW9ucyANCmZ2aXpfc2lsaG91ZXR0ZShhdmdfc2lsKQ0KDQpgYGANCg0KIyMjIyBUaGUgdG90YWwgd2l0aGluLWNsdXN0ZXIgc3VtIG9mIHNxdWFyZXMNCg0KYGBge3J9DQojIENhbGN1bGF0ZSB0b3RhbCB3aXRoaW4tY2x1c3RlciBzdW0gb2Ygc3F1YXJlcw0KdG90YWxfd2l0aGluc3MgPC0ga21lYW5zLnJlc3VsdCR0b3Qud2l0aGluc3MNCmNhdCgiVG90YWwgV2l0aGluLUNsdXN0ZXIgU3VtIG9mIFNxdWFyZXM6Iiwgc3VtKHRvdGFsX3dpdGhpbnNzKSwgIlxuIikNCg0KdHJ1ZV9sYWJlbHMgPC0gYygxLCAxLCAyLCAxLCAyLCAyLCAzLCAzLCA0LCA0KSAgIyBBZGp1c3QgYmFzZWQgb24geW91ciBhY3R1YWwgdHJ1ZSBsYWJlbHMNCg0KY2x1c3Rlcl9hc3NpZ25tZW50cyA8LSBrbWVhbnMucmVzdWx0JGNsdXN0ZXINCiANCmBgYA0KDQojIyMjIEJDdWJlZCByZWNhbGwgYW5kIHByZWNpc2lvbg0KDQpgYGB7cn0NCg0KIyBDYWxjdWxhdGUgQkN1YmVkIHByZWNpc2lvbg0KcHJlY2lzaW9uIDwtIDANCmZvciAoaSBpbiB1bmlxdWUodHJ1ZV9sYWJlbHMpKSB7DQogIGNsdXN0ZXJfaW5kaWNlcyA8LSB3aGljaCh0cnVlX2xhYmVscyA9PSBpKQ0KICBwcmVjaXNpb24gPC0gcHJlY2lzaW9uICsgc3VtKCh0YWJsZShjbHVzdGVyX2Fzc2lnbm1lbnRzW2NsdXN0ZXJfaW5kaWNlc10pICogKHRhYmxlKGNsdXN0ZXJfYXNzaWdubWVudHNbY2x1c3Rlcl9pbmRpY2VzXSkgLSAxKSkgLyBzdW0odGFibGUoY2x1c3Rlcl9hc3NpZ25tZW50c1tjbHVzdGVyX2luZGljZXNdKSkpDQp9DQpwcmVjaXNpb24gPC0gcHJlY2lzaW9uIC8gc3VtKHRhYmxlKGNsdXN0ZXJfYXNzaWdubWVudHMpKQ0KDQojIENhbGN1bGF0ZSBCQ3ViZWQgcmVjYWxsDQpyZWNhbGwgPC0gMA0KZm9yIChqIGluIHVuaXF1ZShjbHVzdGVyX2Fzc2lnbm1lbnRzKSkgew0KICBjbHVzdGVyX2luZGljZXMgPC0gd2hpY2goY2x1c3Rlcl9hc3NpZ25tZW50cyA9PSBqKQ0KICByZWNhbGwgPC0gcmVjYWxsICsgc3VtKCh0YWJsZSh0cnVlX2xhYmVsc1tjbHVzdGVyX2luZGljZXNdKSAqICh0YWJsZSh0cnVlX2xhYmVsc1tjbHVzdGVyX2luZGljZXNdKSAtIDEpKSAvIHN1bSh0YWJsZSh0cnVlX2xhYmVsc1tjbHVzdGVyX2luZGljZXNdKSkpDQp9DQpyZWNhbGwgPC0gcmVjYWxsIC8gc3VtKHRhYmxlKHRydWVfbGFiZWxzKSkNCg0KY2F0KCJCQ3ViZWQgUHJlY2lzaW9uOiIsIHByZWNpc2lvbiwgIlxuIikNCmNhdCgiQkN1YmVkIFJlY2FsbDoiLCByZWNhbGwsICJcbiIpDQoNCg0KYGBgDQoNCiMjIyBUaGUgb3B0aW1hbCBudW1iZXIgb2YgY2x1c3RlcnMNCg0KVG8gZmluZCB0aGUgb3B0aW1hbCBudW1iZXIgb2YgY2x1c3RlcnMgdG8gdXNlIGluIHRoZSBrLW1lYW5zIGFsZ29yaXRobSwgd2UnbGwgdXNlIHRoZcKgKipmdml6X25iY2x1c3QoKSoqwqBmdW5jdGlvbiBmcm9tIHRoZcKgKipmYWN0b2V4dHJhKipwYWNrYWdlIHRvIGNyZWF0ZcKgYSBwbG90IG9mIHRoZSBudW1iZXIgb2YgY2x1c3RlcnMgdnMuIHRoZSB0b3RhbCB3aXRoaW4gc3VtIG9mIHNxdWFyZXMNCg0KYGBge3J9DQojIEZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSB0b3RhbCB3aXRoaW4tY2x1c3RlciBzdW0gb2Ygc3F1YXJlcyAod3NzKQ0Kd3NzIDwtIGZ1bmN0aW9uKGspIHsNCiAga21lYW5zX3Jlc3VsdCA8LSBrbWVhbnMobnVtZXJpY19kYXRhLCBjZW50ZXJzID0gaywgbnN0YXJ0ID0gMTApICAjIFlvdSBjYW4gYWRqdXN0IG5zdGFydCBiYXNlZCBvbiB5b3VyIHByZWZlcmVuY2UNCiAgcmV0dXJuKHN1bShrbWVhbnNfcmVzdWx0JHRvdC53aXRoaW5zcykpDQp9DQoNCiMgQ2FsY3VsYXRlIHRoZSB0b3RhbCB3aXRoaW4tY2x1c3RlciBzdW0gb2Ygc3F1YXJlcyBmb3IgZGlmZmVyZW50IHZhbHVlcyBvZiBrDQprX3ZhbHVlcyA8LSAxOjEwICAjIFlvdSBjYW4gYWRqdXN0IHRoZSByYW5nZSBvZiBrIHZhbHVlcw0Kd3NzX3ZhbHVlcyA8LSBzYXBwbHkoa192YWx1ZXMsIHdzcykNCg0KIyBQbG90IHRoZSBlbGJvdyBjdXJ2ZQ0KcGxvdChrX3ZhbHVlcywgd3NzX3ZhbHVlcywgdHlwZSA9ICJiIiwgcGNoID0gMTksIGZyYW1lID0gRkFMU0UsIA0KICAgICB4bGFiID0gIk51bWJlciBvZiBDbHVzdGVycyAoaykiLCB5bGFiID0gIlRvdGFsIFdpdGhpbi1DbHVzdGVyIFN1bSBvZiBTcXVhcmVzIChXU1MpIiwNCiAgICAgbWFpbiA9ICJFbGJvdyBNZXRob2QiKQ0KDQojIEFkZGluZyBhIGxpbmUgdG8gaW5kaWNhdGUgdGhlICJlbGJvdyINCmFibGluZSh2ID0gd2hpY2goZGlmZih3c3NfdmFsdWVzKSA9PSBtYXgoZGlmZih3c3NfdmFsdWVzKSkpICsgMSwgY29sID0gInJlZCIpDQoNCg0KYGBgDQoNCkFjY29yZGluZyB0byB0aGUgb3V0cHV0IHRoZSBiZXN0IG51bWJlciBvZiBjbHVzdGVycyBpcyBvbmUsDQo=